home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d2 / rnco_mod.arc / RN.ASM < prev    next >
Encoding:
Assembly Source File  |  1988-04-28  |  137.7 KB  |  3,077 lines

  1. ;  RN.ASM
  2. ;                'Copyright 1987 Ziff-Davis Publishing Co.'
  3. ;                 'Michael J. Mefford$'
  4. ; Format       RN [d:][directory]
  5. ;
  6. ;Michael J. Mefford    1987/No. 16 (Utilities)
  7. ;
  8. ;This is a modified version of PC Magazines RN Utility
  9. ;It has Been modified for some special batch tasks.
  10. ;Several new parameters have been added.
  11. ;
  12. ;Purpose:
  13. ;Select, create, rename, delete or backup selected directory.
  14. ;
  15. ;
  16. ;Format:
  17. ;RN [d:][\directory 1] [d:][\directory 2] [/E][/S][/D][/T][/O]
  18. ;                                         [/M1] [/M2] [/M3] [/M4]
  19. ;
  20. ;Directory 1 - RN will display this directory and any subdirectories.
  21. ;Directory 2 - Passed to CO.
  22. ;
  23. ;
  24. ;/E          - Passed to CO.
  25. ;/S          - Passed to CO.
  26. ;/D          - Passed to CO.
  27. ;/T          - Passed to CO.
  28. ;/O          - Passed to CO.
  29. ;/M1         - Exit when return pressed, normally the program goes to CO.
  30. ;/M2         - Don't use Directory 1 parameter pass to CO.
  31. ;/M3         - Passed to CO.
  32. ;/M4         - Passed to CO.
  33. ;
  34. ;Program Functions:
  35. ;
  36. ;         ╔═════════════════════════════╗
  37. ;         ║     PC Magazine RN.COM      ║
  38. ;         ╟─────────────────────────────╢
  39. ;         ║ Enter ─┘ to Select Directry║
  40. ;         ║ F2  ^Exit to DOS            ║
  41. ;         ║                             ║
  42. ;         ║ F4  ^File Maintenance       ║
  43. ;         ║ F5  ^Rename Directory       ║
  44. ;         ║ F6   Delete dir & all files ║
  45. ;         ║ F7  ^Make a new Directory   ║
  46. ;         ║ F8  ^Change Backup/Rest Parm║
  47. ;         ║ F9  ^Backup Directory       ║
  48. ;         ║ F10  Restore Directory      ║
  49. ;         ║  Backup/Restore Parameters  ║
  50. ;         ║  ^Dr=A: ^Path=*.*           ║
  51. ;         ║  ^Options=/S                ║
  52. ;         ║ Esc to Cancel Program       ║
  53. ;         ╚═════════════════════════════╝
  54. ;             Use:   PgUp PgDn
  55. ;            ^PgUp ^PgDn Home End
  56. ;
  57. ;
  58. ;Modified by Bob Hunt 414-287-3308
  59.  
  60. CODE SEGMENT                           ;*************************
  61. ASSUME CS:CODE,DS:CODE                 ;*                       *
  62. ORG 100H                               ;*  REMEMBER TO EXE2BIN  *
  63.                                        ;*                       *
  64. START:         JMP    BEGINNING        ;*************************
  65.  
  66. ;;             DATA AREA
  67. ;              ---------
  68. USE_DIRECTORY  DB   12 DUP (32),0 ;DISPLAY ONLY THIS DIRECTORY
  69. SAVE_LAST_SLASH DW  0
  70. IS_THERE_FILE  DB  0
  71. USE_DIR_EQ     DB     ?              ;CUR = USE_DIRECTORY
  72. SAVE_SORT      DB     '/N'           ;SAVE SORT PARM FOR CO OR DR
  73. TEMPUS_RETCODE DB     0         ;return code
  74. MENU_TYPE      DB     0              ; MENU TYPE FROM PARMS
  75. INSTALL_MSG    DB     'RN sucessfully installed',13,10
  76. COPYRIGHT      DB     'Copyright 1987 Ziff-Davis Publishing Co.',13,10
  77. PROGRAMMER     DB     'Michael J. Mefford$',1AH
  78. NO_FREE        DB     'Too many resident programs$'
  79. REQUIRES       DB     'Requires DOS 2.x$'
  80. NOT_ENOUGH     DB     'Requires 128K free RAM$'
  81. UNKNOWN        DB     'Drive not supported$'
  82. HEADING        DB     'Select a Directory from drive ',0
  83. DIR_MSG        DB     ' directories',0
  84. FILE_COUNT     DB     ' files in ',0
  85. PATH_ERROR     DB     'PROGRAM CO.COM NOT FOUND',0
  86. BACKUP_USES    DB     'Backup will use ',0
  87. BACKUP_USES_1_2MEG DB     ' 1.2Meg (Red) disks',0
  88. BACKUP_USES_1_4MEG DB     ' 1.4Meg(3 1/2") disks',0
  89. BACKUP_USES_360K   DB     ' 360k disks',0
  90. FORMAT_MSG     DB     'Format disketts (Y) or (N)?',0
  91. USING          DB     ' using ',0
  92. LOADING        DB     'Loading and sorting directories',13,10,0
  93. RENAME_MSG     DB     'Enter new name for ',0
  94. PATH_LENGTH    DB     'Path length is now ',0
  95.                DB     '.  Maximum is 63.',0
  96. MKDIR_MSG1     DB     'We suggest using your LAST NAME ',0
  97. MKDIR_MSG      DB     'Enter new subdirectory Name for ',0
  98. RMDIR_MSG0     DB     'Directory Deleted 0 files in directory',0
  99. RMDIR_MSG      DB     'Warning: All files will be lost.    ',0
  100.                DB     'Do you still wish to remove it?  Y/N ',0
  101. RMDIR_MSG2     DB     'Are you sure you want to DELETE ',0
  102.                DB     'EVERYTHING in this directory???? Y/N ',0
  103. HIDE_MSG       DB     'H to hide or U to unhide ',0
  104. READ_ONLY_MSG  DB     'R to mark read-only U to undo read-only',0
  105. ARCHIVE_MSG    DB     'S to set R to reset archive bit',0
  106. HAVE_BEEN      DB     'have been marked ',0
  107.                DB     'not to be BACKUPed.',0
  108. READ_MSG       DB     'not read-only.',0
  109. BRDRIVE_MSG    DB     'Enter disk drive letter ',0
  110. BRPATH_MSG     DB     'Enter DOS Path ',0
  111. BROPTIONS_MSG  DB     'Enter Backup/Restore Options ',0
  112. BS             DB     8,32,8,0
  113.  
  114. DATA_INT       DB     0
  115. DATA_SEGMENT   DW     ?
  116.  
  117. DOS_VERSION    DB     ?
  118. ROOT           DB     '\ (ROOT)'
  119. ROOT_DIR       DB     '\',0
  120. DOT_DOT        DB     '..',0
  121. STAR_DOT_STAR  DB     '*.*',0
  122. CLUST_BYTES_1_2MEG  DW     512
  123. CLUSTERS_1_2MEG     DW     2371-1
  124. CLUST_COUNT_1_2MEG  DW     ?
  125. T_CLUST_COUNT_1_2MEG  DW     ?
  126. DISKS_1_2MEG        DW     ?
  127. CLUST_BYTES_1_4MEG  DW     512
  128. CLUSTERS_1_4MEG     DW     2847-1
  129. CLUST_COUNT_1_4MEG  DW     ?
  130. T_CLUST_COUNT_1_4MEG  DW     ?
  131. DISKS_1_4MEG        DW     ?
  132. CLUST_BYTES_360K    DW     1024
  133. CLUSTERS_360K       DW     354-1
  134. CLUST_COUNT_360K    DW     ?
  135. T_CLUST_COUNT_360K    DW     ?
  136. DISKS_360K          DW     ?
  137. DEFAULT_DIR    DB   64 DUP (00),0 ;CURRENT DIRECTORY WHEN PROG ENTERED
  138. DEFAULT_DRIVE  DB     ?
  139. DRIVE          DB     ?
  140. ROOT_SECTORS   DW     ?
  141. CLUST_RECORDS  DW     ?
  142. CLUST_SECTORS  DW     ?
  143. CLUST_BYTES    DW     ?
  144. CLUST_COUNT    DW     ?
  145. LAST_CLUSTER   DW     ?
  146. LAST_ENTRY     DW     ?
  147. END_OFFSET     DW     ?
  148. AT_LAST_LINE   DB     0
  149. STRIP_MASK     DB     ?
  150. ADD_MASK       DB     ?
  151.  
  152. STATUS_REG     DW     ?
  153. VIDEO_SEG      DW     0B000H
  154. NORMAL         DB     07H
  155. INVERSE        DB     70H
  156. BAR_ATTRIBUTE  DB     70H
  157. ATTR_TREE      DB     07H
  158. ATTR_MENU      DB     07H
  159. ATTR_TEXT      DB     07H
  160. ATTR_MSGS      DB     07H
  161. CURSOR_TYPE    DW     ?
  162. CUR_OFFSET_SAVE DW    ?          ; SAVE CURRENT OFFSET
  163. CUR_OFFSET     DW     DIRECTORIES
  164. CUR_RECORD     DW     ?
  165. CUR_LEVEL      DW     ?          ;SAVE CURRENT LEVEL
  166. CUR_LEVEL_SAVE DW     ?          ;SAVE LEVEL
  167. PAGE_START     EQU    323
  168. PAGE_END       DW     21*160+PAGE_START
  169. LINE           DW     PAGE_START
  170. LINE_SAVE      DW     PAGE_START ; SAVE CURRENT LINE
  171. DIR_COUNT      DW     1
  172. COUNT          DW     ?
  173. COUNT_SAVE     DW     ?
  174. BAR_START      DW     PAGE_START
  175. BAR_LENGTH     DW     8
  176. SEARCH_COUNT   DW     ?
  177. DIR_NAME       DW     ?
  178.  
  179. SAVE_DS_PATH   DW     0
  180. SAVE_SI_PATH   DW     0
  181. PATH           DB     0,'PATH='
  182. PATH_FOR_PGM   DB     76 DUP (00),0 ;STORE PATH= FOR EXECUTE
  183. COMSPEC        DB     'COMSPEC='
  184. PARA_BR        DB     60 DUP (00)
  185. PARA_BACKUP    DB     '/C BACKUP ',0
  186. PARA_ADD       DW     '  '
  187. PARA_RESTORE   DB     '/C RESTORE ',0
  188. PARA_FORMAT    DB     '/C FORMAT ',0
  189. PARAMETER      DB     '/C CO /M4 /N ',0
  190. PARAMETER_DOS  DB     '/C DIR  ',0
  191. PARM_SAVE_LGTH DB     0
  192. PARM_SAVE      DB     101 DUP (0D)
  193. LOAD_NAME_CO   DB     '\CO.COM'
  194.                DB     0
  195.  
  196. ENVIRONMENT    DW     ?
  197. COM_LINE_PTR   DD     OFFSET PARAMETER
  198. STACK_SEG      DW     ?
  199. STACK_PTR      DW     ?
  200.  
  201. DIR_RECORD     EQU    40
  202. DATA_RECORD    EQU    20
  203.  
  204. ROOT_DIRECTORY EQU    0
  205. FAT            EQU    ROOT_DIRECTORY
  206. WORKSPACE      EQU    65535-16384
  207.  
  208. K_ESC           EQU  1
  209. K_MINUS         EQU  12
  210. K_PLUS          EQU  13
  211. K_BACKSPACE     EQU  14
  212. K_E             EQU  18
  213. K_R             EQU  18
  214. K_T             EQU  20
  215. K_Y             EQU  21
  216. K_O             EQU  24
  217. K_P             EQU  25
  218. K_ENTER         EQU  28
  219. K_S             EQU  31
  220. K_D             EQU  32
  221. K_F             EQU  33
  222. K_C             EQU  46
  223. K_V             EQU  47
  224. K_B             EQU  48
  225. K_N             EQU  49
  226. K_M             EQU  50
  227. K_F1            EQU  59
  228. K_F2            EQU  60
  229. K_F3            EQU  61
  230. K_F4            EQU  62
  231. K_F5            EQU  63
  232. K_F6            EQU  64
  233. K_F7            EQU  65
  234. K_F8            EQU  66
  235. K_F9            EQU  67
  236. K_F10           EQU  68
  237. K_NUM_LOCK      EQU  69
  238. K_SCROLL_LOCK   EQU  70
  239. K_HOME          EQU  71
  240. K_UP_ARROW      EQU  72
  241. K_PGUP          EQU  73
  242. K_PRTSC         EQU  55
  243. KN_MINUS        EQU  74
  244. K_LEFT_ARROW    EQU  75
  245. K_RIGHT_ARROW   EQU  77
  246. KN_PLUS         EQU  78
  247. K_END           EQU  79
  248. K_DOWN_ARROW    EQU  80
  249. K_PGDN          EQU  81
  250. K_INS           EQU  82
  251. K_DEL           EQU  83
  252. K_LEFT_SHIFT    EQU  42
  253. K_RIGHT_SHIFT   EQU  36
  254. K_TAB           EQU  15
  255. K_CTRL          EQU  29
  256. K_ALT           EQU  56
  257. K_SPACE         EQU  57
  258. K_CAPS_LOCK     EQU  58
  259. K_CTRL_PGDN     EQU  118
  260. K_CTRL_PGUP     EQU  132
  261.  
  262. DEFAULT_MENU_NO DB  2        ;DEFAULT IS SMALL MENU
  263. DEFAULT_MENU    DB  2        ;DEFAULT IS SMALL MENU
  264.  
  265. DISPATCH_KEY   DB  K_ESC,
  266.                DB  K_ENTER
  267.                DB  K_F3
  268.                DB  K_F1, K_F2,        K_F7
  269.                DB  K_E
  270.                DB  K_F5, K_F6,        K_F8,   K_F4
  271.                DB  K_F9
  272.                DB  K_B
  273.                DB  K_F10,       K_HOME, K_UP_ARROW,  K_PGUP
  274.                DB  K_END,K_DOWN_ARROW,K_PGDN, K_CTRL_PGDN, K_CTRL_PGUP
  275.                DB  K_F,  K_R,         K_C,         K_M
  276.                DB  K_D,  K_P,         K_O
  277. DISPATCH_CNT   EQU $ - DISPATCH_KEY
  278.  
  279. DISPATCH_TABLE DW  ESC_EXIT
  280. MENU_1         DW  SELECT_DIR
  281.                DW  NO_OP
  282.                DW  HELP,     EXIT_DOS,    MKDIR
  283.                DW  EXIT_DOS
  284.                DW  RENAME,   RMDIR,       B_R_OPTIONS, CO
  285.                DW  BACKUP
  286.                DW  BACKUP
  287.                DW  RESTORE,     HOME_BAR,    UP_ARROW,    PG_UP
  288.                DW  END_BAR,  DN_ARROW,    PG_DN,       BOTTOM_BAR,  TOP_BAR
  289.                DW  CO,       RENAME,      B_R_OPTIONS, MKDIR
  290.                DW  BRDRIVE,  BRPATH,      BROPTIONS
  291. DISPATCH_END   EQU $ - 2
  292.  
  293. ;----------------------FW SMALL MENU -------------------------------
  294. DISPATCH_KEY2  DB  K_ESC,
  295.                DB  K_ENTER
  296.                DB  K_F2
  297.                DB  K_F4
  298.                DB  K_HOME,K_UP_ARROW,  K_PGUP
  299.                DB  K_END, K_DOWN_ARROW,K_PGDN, K_CTRL_PGDN, K_CTRL_PGUP
  300. DISPATCH_CNT2  EQU $ - DISPATCH_KEY2
  301.  
  302. DISPATCH_TABLE2 DW  ESC_EXIT
  303. MENU_2         DW  SELECT_DIR
  304.                DW  NEW_USER
  305.                DW  NEW_MENU
  306.                DW  HOME_BAR, UP_ARROW,  PG_UP
  307.                DW  END_BAR,  DN_ARROW,  PG_DN,  BOTTOM_BAR,  TOP_BAR
  308. DISPATCH_END2  EQU $ - 2
  309. ;-------------------------------------------------------------------
  310.  
  311. MENU_WIDTH   EQU  31
  312. MENU_LGTH    EQU  20
  313. MENU  LABEL  BYTE
  314.             DB  201,29 DUP (205),187,
  315.             DB  186,'      PC Magazine RN.COM     ',186
  316.             DB  199,29 DUP (196),182
  317.             DB  186,' Enter ',17,196,217,' to Select Directry',186
  318.             DB  186,' F2  ^Exit to DOS            ',186
  319.             DB  186,'                             ',186
  320.             DB  186,' F4  ^File Maintenance       ',186
  321. ROPTION     DB  186,' F5  ^Rename Directory       ',186
  322. RLINE       EQU ROPTION+1
  323.             DB  186,' F6   Delete dir & all files ',186
  324.             DB  186,' F7  ^Make a new Directory   ',186
  325.             DB  186,' F8  ^Change Backup/Rest Parm',186
  326.             DB  186,' F9  ^Backup Directory       ',186
  327.             DB  186,' F10  Restore Directory      ',186
  328.             DB  186,'  Backup/Restore Parameters  ',186
  329. CDRIVE      DB  186,'  ^Dr=A: ^Path=*.*           ',186
  330. ODRIVE      EQU CDRIVE+7
  331. OPATH       EQU CDRIVE+16
  332. COPTIONS    DB  186,'  ^Options=/S                ',186
  333. OOPTIONS    EQU COPTIONS+12
  334.             DB  186,' Esc to Cancel Program       ',186
  335.             DB  200,29 DUP (205),188,
  336.             DB '      Use: ',24,32,25,' PgUp PgDn       '
  337.             DB    '     ^PgUp ^PgDn Home End      '
  338.  
  339. MENU2 LABEL  BYTE
  340.             DB  201,29 DUP (205),187,
  341.             DB  186,'      PC Magazine RN.COM     ',186
  342.             DB  199,29 DUP (196),182
  343.             DB  186,'To SELECT, use the ',24,' ',25,' cursor',186
  344.             DB  186,' keys or the mouse to move   ',186
  345.             DB  186,' the HIGHLIGHTED box to the  ',186
  346.             DB  186,' Directory you wish, press   ',186
  347.             DB  186,' the left mouse botton or the',186
  348.             DB  186,'Enter ',17,196,217,' key.               ',186
  349.             DB  186,'                             ',186
  350.             DB  186,' F2  NEW USERS press F2 Key  ',186
  351.             DB  186,'     to Create Data Directory',186
  352.             DB  186,'                             ',186
  353.             DB  186,' F4  Maintenance functions   ',186
  354.             DB  186,'     for Directories & Files.',186
  355.             DB  186,'                             ',186
  356.             DB  186,' Esc to Cancel Program       ',186
  357.             DB  200,29 DUP (205),188,
  358.             DB '      Use: ',24,32,25,' PgUp PgDn       '
  359.             DB    '     ^PgUp ^PgDn Home End      '
  360. ; DB  201,20 DUP (205),187,186,' PC Magazine RN.COM ',186
  361. ; DB  186,' (C) Copr. 1987 ZD  ',186,186,' Michael J. Mefford ',186
  362. ; DB  199,20 DUP (196),182,186,' F1   ChDir (or ',17,196,217,')',186
  363. ;DB  186,' F2   Rename        ',186,186,' F3   MkDir         ',186
  364. ;DB  186,' F4   RmDir         ',186,186,' F5   Hide/Unhide   ',186
  365. ;DB  186,' F6   Do/Undo R-O   ',186,186,' F7   Set/Reset Arc ',186
  366. ;DB  186,' F8   Reread        ',186,186,' F9   File count    ',186
  367. ;DB  186,' F10  DR            ',186,186,' Esc  to End        ',186
  368. ;DB  200,20 DUP (205),188,'  Use: ',24,32,25,' PgUp PgDn  '
  369. ;DB  ' ^PgUp ^PgDn Home End '
  370.  
  371. ;---------------------------------------------------------------------;
  372. ; Store our data segment.  We will be writing directly to the screen  ;
  373. ; buffer so we need the display card address and the status register. ;
  374. ;---------------------------------------------------------------------;
  375.  
  376. ;              CODE AREA
  377. ;              ---------
  378. BEGINNING:     CLD                     ;String moves in forward direction.
  379.                PUSH   DS
  380.                POP    DATA_SEGMENT     ;Store our data segment.
  381.                MOV    AX,3301H         ;Turn Control Break off.
  382.                MOV    DL,0
  383.                INT    21H
  384.  
  385.                MOV    AX,40H           ;Point to the ROM BIOS data area
  386.                MOV    DS,AX            ; and get base address of active
  387.                MOV    AX,DS:[63H]      ; display card.
  388.                ADD    AX,6             ;Add six to get status register
  389.                PUSH   CS               ;Done there, so restore data segment.
  390.                POP    DS
  391.                MOV    STATUS_REG,AX    ;Store status register.
  392.                CMP    AX,3BAH          ;Status port of MONO card is 3BAh.
  393.                JZ     MONO             ;If that's what we got, it's MONO
  394.                MOV    VIDEO_SEG,0B800H       ; else COLOR so add 800h.
  395.                XOR    BH,BH                  ;Get current attribute
  396.                MOV    AH,8                   ; of display page zero.
  397.                INT    10H
  398.                MOV    NORMAL,AH              ;Store it.
  399.                MOV    AH,07
  400.                XOR    AH,1110111xB           ;Flip color bits.
  401.                MOV    INVERSE,AH             ;Save it.
  402.                MOV    BAR_ATTRIBUTE,AH
  403.                MOV    ATTR_TREE,14           ;Store it.
  404.                MOV    ATTR_MENU,03           ;Store it.
  405.                MOV    ATTR_TEXT,02           ;Store it.
  406.                MOV    ATTR_MSGS,04           ;Store it.
  407. MONO:          XOR    BH,BH
  408.                MOV    AH,3                   ;Retrieve cursor type.
  409.                INT    10H
  410.                MOV    CURSOR_TYPE,CX         ;And save it.
  411.                CALL   CURSOR_OFF
  412.  
  413. ;---------------------------------------------;
  414. ; Check DOS version and allocate 128K memory. ;
  415. ;---------------------------------------------;
  416.  
  417.                MOV    AH,30H                 ;Get DOS version.
  418.                INT    21H
  419.                MOV    DOS_VERSION,AL         ;And save.
  420.                CMP    AL,2                   ;Is it 2.x or above?
  421.                JAE    CONTINUE               ;If yes, continue.
  422.  
  423.                MOV    DX,OFFSET REQUIRES     ;Else, exit with message.
  424. QUIT:          JMP    MSG_EXIT
  425.  
  426. CONTINUE:      CMP    AL,3                          ;Is it DOS 3.x or above?
  427.                JAE    RENAME_OK                     ;If yes continue.
  428.                MOV    RLINE,'N'                     ;Else mark rename function
  429.                MOV    RLINE+1,'/'                   ; Not/Available.
  430.                MOV    RLINE+2,'A'
  431. RENAME_OK:     MOV    AH,49H                        ;Return our memory segment.
  432.                INT    21H
  433.                MOV    BX,2000H               ;Request 128K.
  434.                MOV    AH,4AH
  435.                INT    21H
  436.                MOV    DX,OFFSET NOT_ENOUGH   ;If not available, exit
  437.                JC     QUIT                   ; with message.
  438.  
  439.                MOV    AH,19H                 ;Get default drive and save.
  440.                INT    21H
  441.                MOV    DEFAULT_DRIVE,AL
  442.  
  443.                MOV    SI,OFFSET DEFAULT_DIR  ;Point to default directory.
  444.                MOV    BYTE PTR [SI],'\'      ;DOS fails to include starting "\".
  445.                INC    SI                     ;Point to first level.
  446.                MOV    DL,DEFAULT_DRIVE       ;Retrieve drive.
  447.                INC    DL                     ;Convert to DOS format.
  448.                MOV    AH,47H                 ;Retrieve current directory.
  449.                INT    21H
  450.                CALL   CAPITALIZE             ;Capitalize it.
  451.  
  452. ;-----------------------------------------------------;
  453. ; Check for drive request.  Retrieve Disk Block info. ;
  454. ;-----------------------------------------------------;
  455.  
  456.                MOV    AL,DS:[5CH]            ;Get drive request.
  457.                MOV    BL,AL                  ;Save it.
  458.                DEC    AL                     ;Adjust.
  459.                OR     BL,BL                  ;If it was zero, no request.
  460.                JNZ    STORE_DRIVE
  461.  
  462.                MOV    AH,19H                 ;Then get default drive.
  463.                INT    21H
  464. STORE_DRIVE:   MOV    DRIVE,AL               ;Store it.
  465.                MOV    DL,AL
  466.                MOV    AH,0EH                 ;Change drive to requested.
  467.                INT    21H
  468.  
  469.                MOV    DL,DRIVE               ;Retrieve drive.
  470.                INC    DL                     ;Adjust.
  471.                MOV    AH,32H                 ;Retrieve Disk Block.
  472.                INT    21H
  473.                OR     AL,AL                  ;Does disk request exist?
  474.                JZ     EXISTS
  475.                JMP    DISK_EXIT              ;If no, exit with message.
  476. EXISTS:        MOV    SI,BX                  ;Store Disk Block.
  477.                MOV    DI,OFFSET DISK_BLOCK
  478.                MOV    CX,18
  479.                REP    MOVSB
  480.                PUSH   CS                     ;Restore data segment.
  481.                POP    DS
  482.  
  483.                CMP    DRIVE,1                ;Is drive request A: or B:?
  484.                JA     CK_FREE
  485.                JMP    READ                   ;If yes, automatic read.
  486.  
  487. ;---------------------------------------------------;
  488. ; Check to see if our database has been installed.  ;
  489. ;---------------------------------------------------;
  490.  
  491. CK_FREE:       MOV    AL,60H - 1             ;Available vectors are 60H - 67H.
  492. FREE_USER_INT: INC    AL
  493.                MOV    AH,35H                 ;Get vector address.
  494.                INT    21H
  495.                CMP    BX,0                   ;Is offset being used?
  496.                JNZ    CK_SIGNATURE           ;If yes, see if it's us.
  497.                MOV    DX,ES
  498.                CMP    DX,0                   ;Is segment being used?
  499.                JNZ    CK_SIGNATURE           ;If yes, see if it's us.
  500.                MOV    DATA_INT,AL            ;If available, save INT number.
  501.                JMP    SHORT NEXT_USER        ;Check all 7.
  502.  
  503. CK_SIGNATURE:  MOV    DI,BX                  ;See if INT has our signature.
  504.                MOV    SI,OFFSET INSTALL_MSG
  505.                MOV    CX,30/2
  506.                REPZ   CMPSW
  507.                JNZ    NEXT_USER
  508.                JMP    CK_SUBST           ;If yes, already installed.
  509.  
  510. NEXT_USER:     CMP    AL,67H                 ;Have we checked all 7?
  511.                JNZ    FREE_USER_INT          ;If no, next one.
  512.                CMP    DATA_INT,0             ;Did we find one that was free?
  513.                JNZ    CK_SWITCH
  514.                MOV    DX,OFFSET NO_FREE      ;If no, exit with message.
  515.                JMP    ERROR_EXIT
  516.  
  517. CK_SWITCH:     PUSH   ES                     ;Restore data segment.
  518.                MOV    ES,DS
  519. ;------------------------FW-------------------------------------------
  520.                MOV    SI,80H                 ;See if request to install.
  521.                XOR    AX,AX
  522.                LODSB
  523.                MOV    CX,AX
  524.                MOV    DI,OFFSET PARM_SAVE    ;SET TO TYPE MENU STORE
  525.                REPNZ  MOVSB
  526.                MOV    BYTE PTR [DI]," "
  527.                INC    DI
  528.                MOV    BYTE PTR [DI],"-"
  529.                INC    DI
  530.                MOV    BYTE PTR [DI],0D       ;PUT IN CARRIAGE RETURN
  531.                MOV    AX,DI                  ;NEW PARM LGHT
  532.                SUB    AX,OFFSET PARM_SAVE    ;SET TO TYPE MENU STORE
  533.                MOV    PARM_SAVE_LGTH,AL      ;SAVE LGTH
  534. ;---------------------------------------------------------------------
  535.                MOV    SI,80H                 ;See if request to install.
  536.                LODSB
  537.                CMP    AL,0                   ;If no parameters, read data.
  538.                JNE    NEXT_SWITCH
  539.                JMP    CK_SWITCH_END
  540. NEXT_SWITCH:   LODSB
  541.                CMP    AL,0                   ;If 00 END
  542.                JNE    CK_CR_RETURN
  543.                JMP    CK_SWITCH_END
  544. CK_CR_RETURN:  CMP    AL,13                  ;End of parameters?
  545.                JNE    CK_SLASH
  546.                JMP    CK_SWITCH_END          ;If yes, read data.
  547. CK_SLASH:      CMP    AL,'\'                 ;DIRECTORY?
  548.                JZ     SAVE_DIR
  549.                CMP    AL,'/'                 ;Switch character?
  550.                JNZ    NEXT_SWITCH
  551.                MOV    BL,BYTE PTR [SI]       ;LOAD CHAR
  552.                AND    BL,5FH                 ;CAPITALIZE
  553.                CMP    BL,'M'                 ;=M?
  554.                JE     MENU_CHK               ;YES
  555.                MOV    DI,OFFSET SAVE_SORT    ;SET TO BEGIN OF RECORD
  556.                STOSB
  557.                LODSB
  558.                CMP    AL,13                  ;End of parameters?
  559.                JZ     CK_SWITCH_END                   ;If yes, read data.
  560.                STOSB
  561.                JMP    NEXT_SWITCH
  562. ;----------------------FW CHANGE-------------------------------------
  563. MENU_CHK:      LODSB                         ;LOAD M
  564.                LODSB                         ;LOAD MENU CODE
  565.                MOV    DI,OFFSET MENU_TYPE    ;SET TO TYPE MENU STORE
  566.                STOSB                         ;STORE MENU CODE
  567. MENU_CK_1:     CMP  MENU_TYPE,'1'            ;MENU 1? EXIT WHEN RETURN HIT
  568.                JNZ  MENU_CK_2                ;NO
  569.                MOV  BX,OFFSET CHANGE_DIR     ;GO TO
  570.                MOV  WORD PTR MENU_1,BX       ; CHANGE DIR NOT SELECT
  571.                MOV  WORD PTR MENU_2,BX       ; CHANGE DIR NOT SELECT
  572. MENU_CK_2:     CMP  MENU_TYPE,'2'            ;MENU 2?
  573.                JNZ  MENU_CK_L                ;NO
  574.                MOV  USE_DIRECTORY,32         ;DONT USE DIRECTORY NAME
  575.                ;Menu "/M3" is used in CO.com
  576.                ;Menu "/M4" is used in CO.com
  577. MENU_CK_L:     JMP    NEXT_SWITCH
  578. SAVE_DIR:      PUSH   CS                     ;Restore data segment.
  579.                MOV    DI,OFFSET USE_DIRECTORY ;SET TO BEGIN OF RECORD
  580.                MOV    SAVE_LAST_SLASH,DI     ;SAVE POINTER
  581. SAVE_DIR_LOOP: LODSB
  582.                CMP    AL,13                  ;End of parameters?
  583.                JZ     CK_SWITCH_END          ;If yes, read data.
  584.                CMP    AL,32                  ;End of parameter?
  585.                JZ     NEXT_SWITCH            ;If yes, NEXT PARAM
  586. CHECK_COLEN:   CMP    AL,':'                 ;IS THERE A :
  587.                JNE    CHECK_SLASH
  588.                MOV    SAVE_LAST_SLASH,DI     ;SAVE POINTER
  589.                INC    SAVE_LAST_SLASH
  590. CHECK_SLASH:   CMP    AL,'\'                 ;IS THERE A \
  591.                JNE    CHECK_ASTRISK
  592.                MOV    SAVE_LAST_SLASH,DI     ;SAVE POINTER
  593. CHECK_ASTRISK: CMP    AL,'*'                 ;IS THERE A *
  594.                JNE    CHECK_QUESTION
  595.                MOV    IS_THERE_FILE,1        ;SAY YES
  596. CHECK_QUESTION: CMP   AL,'?'                 ;IS THERE A ?
  597.                JNE    CHECK_DONE
  598.                MOV    IS_THERE_FILE,1        ;SAY YES
  599. CHECK_DONE:    CMP    AL,'.'                 ;End of parameter?
  600.                JZ     SAVE_DIR_LOOP
  601.                CMP    AL,'A'                 ;End of parameter?
  602.                JL     CK_SWITCH_NT           ;If yes, NEXT PARAM
  603.                AND    AL,5FH                 ;CAPITALIZE
  604. CK_SWITCH_NT:  STOSB                         ;STORE IN USE_DIRECTORY
  605.                JMP    SAVE_DIR_LOOP
  606. CK_SWITCH_END:
  607.                CMP    IS_THERE_FILE,0        ;WAS THERE A FILE
  608.                JE     NO_FILE                ;NO
  609.                MOV    SI,SAVE_LAST_SLASH
  610. LOOP_BLANKS:   CMP    BYTE PTR [SI],0
  611.                JE     NO_FILE
  612.                MOV    BYTE PTR [SI],32
  613.                INC    SI
  614.                JMP    LOOP_BLANKS
  615. NO_FILE:       POP    ES                     ;Restore segment.
  616.                CMP    SAVE_SORT+1,'I'        ;IS PARM I
  617.                JNZ    READ
  618. ;--------------------------------------------------------------------
  619.  
  620. INSTALL:       MOV    DX,103H                ;If yes, point to signature.
  621.                MOV    AL,DATA_INT            ;Retrieve free INT number.
  622.                MOV    AH,25H                 ;And install.
  623.                INT    21H
  624.                CALL   FIRST_READ             ;Read disk data.
  625.                CALL   CLS
  626.                MOV    DX,OFFSET INSTALL_MSG  ;Display install message.
  627.                MOV    AH,9
  628.                INT    21H
  629.                CALL   RESTORE_DRIVE          ;Restore defaults.
  630.                CALL   CURSOR_ON
  631.                MOV    DX,OFFSET END_RESIDENT
  632.                INT    27H                    ;Terminate and stay resident.
  633.  
  634. ;-----------------------------------------------------;
  635. ; Check to see if drive request is a substitute.      ;
  636. ; Also if different from current resident drive data. ;
  637. ;-----------------------------------------------------;
  638.  
  639. CK_SUBST:      MOV    DATA_SEGMENT,ES        ;Save the location of disk data.
  640.                PUSH   ES:CLUST_BYTES         ;Retrieve from resident database
  641.                POP    CLUST_BYTES            ; cluster size in bytes.
  642.                MOV    AL,DRIVE
  643.                MOV    DX,OFFSET UNKNOWN      ;Is it a substituted drive?
  644.                CMP    AL,BYTE PTR DISK_BLOCK
  645.                JZ     CK_NEW_DRIVE           ;If yes, exit with message.
  646.                JMP    DISK_EXIT
  647.  
  648. CK_NEW_DRIVE:  CMP    AL,ES:DRIVE            ;Is it a new drive request?
  649.                JZ     FORMAT                 ;If no, format resident data.
  650.                MOV    ES:DRIVE,AL            ;Else, save new drive.
  651.  
  652. ;--------------------------------------------------------------------;
  653. ; Read disk directory data, if necessary.  Format it into a tree.    ;
  654. ; Mark the current default directory.  Clear the screen and display. ;
  655. ;--------------------------------------------------------------------;
  656.  
  657. READ:          CALL   FIRST_READ
  658. FORMAT:        CALL   FORMAT_IT
  659.                CALL   GET_CURRENT
  660. ;--------------FW CHANGE---------------------------------------------
  661.                CMP    USE_DIRECTORY,32        ;USING A DIRECTORY NAME
  662.                JNZ    USE_SHORT_MENU
  663.                MOV    DEFAULT_MENU_NO,1      ;DEFAULT IS lONG MENU
  664.                MOV    DEFAULT_MENU,1         ;DEFAULT IS lONG MENU
  665. USE_SHORT_MENU:
  666. ;--------------------------------------------------------------------
  667.                CALL   CLS
  668.                CALL   START_DISPLAY
  669. ;--------------FW CHANGE---------------------------------------------
  670. ;              CALL   FILE_SUM               ;WRITE NO FILES
  671. ;--------------------------------------------------------------------
  672.  
  673. ;-----------------------------------------;
  674. ; We are now ready for business.  We will ;
  675. ; loop here, waiting for user keystokes.  ;
  676. ;-----------------------------------------;
  677.  
  678. GET_KEY:       CALL   UPDATE_SCREEN
  679.                CALL   READ_KEY               ;Get a keystroke.
  680.                MOV    BX,AX                  ;Save returned key.
  681.                CMP    AH,1                   ;Is it Esc or below?
  682.                JBE    FUNCTION               ;If yes, function.
  683.                CMP    AH,36H                 ;Is it right shift or above?
  684.                JAE    FUNCTION               ;If yes, function.
  685.                CMP    AH,1CH                 ;Is it CR?
  686.                JE     FUNCTION               ;If yes, function.
  687.                MOV    AH,2                   ;Get shift state.
  688.                INT    16H
  689.                TEST   AL,4                   ;Is Ctrl depressed?
  690.                JNZ    FUNCTION               ;If no, check function request.
  691.                CALL   SEARCH                 ;Else, search request.
  692.                JMP    SHORT GET_KEY
  693.  
  694. FUNCTION:      CMP    DEFAULT_MENU,2
  695.                JE     FUNCTION2
  696.  
  697.                MOV    DI,OFFSET DISPATCH_KEY
  698.                MOV    AL,BH
  699.                MOV    CX,DISPATCH_CNT        ;Valid commands.
  700.                REPNZ  SCASB
  701.                JNZ    GET_KEY                ;If no match, get another.
  702.                MOV    DI,OFFSET DISPATCH_END
  703.                JMP    FUNCTION_EXE
  704.  
  705. FUNCTION2:     MOV    DI,OFFSET DISPATCH_KEY2
  706.                MOV    AL,BH
  707.                MOV    CX,DISPATCH_CNT2       ;Valid commands.
  708.                REPNZ  SCASB
  709.                JNZ    GET_KEY                ;If no match, get another.
  710.                MOV    DI,OFFSET DISPATCH_END2
  711.  
  712. FUNCTION_EXE:  SHL    CX,1
  713.                SUB    DI,CX
  714.                CALL   DS:[DI]                ;Else do subroutine.
  715. ;--------------FW CHANGE---------------------------------------------
  716. ;              CALL   FILE_SUM               ;WRITE NO FILES
  717. ;--------------------------------------------------------------------
  718.                JMP    SHORT GET_KEY          ;Update screen; get next command.
  719.  
  720. ;-------------------------------------------------------------------;
  721. ; This is the exit routine. Restore defaults the way we found them. ;
  722. ;-------------------------------------------------------------------;
  723.  
  724. ESC_EXIT:
  725.                MOV  AL,DEFAULT_MENU_NO
  726.                CMP  DEFAULT_MENU,AL               ;IS IT LONG MENU
  727.                JE   EXIT_PGM               ;NO EXIT
  728.                MOV  DEFAULT_MENU,AL               ;DEFAULT TO LONG MENU
  729.                CALL START_DISPLAY          ;AND DISPLAY IT
  730.                RET
  731. EXIT_PGM:      MOV    DX,OFFSET CURRENT_DIR
  732.                MOV    TEMPUS_RETCODE,3        ;SET RETURN CODE
  733.                CALL   CD
  734. EXIT:          CALL   RESTORE_DRIVE
  735.                CALL   CLS
  736.                CALL   CURSOR_ON
  737.                XOR    DX,DX                  ;Home cursor.
  738.                CALL   SET_CURSOR
  739.                MOV    AL,TEMPUS_RETCODE       ;SET RETURN CODE
  740.                MOV    AH,4CH
  741.                INT    21H                     ;OUT
  742.  
  743.                ;*************;
  744.                ; SUBROUTINES ;
  745.                ;*************;
  746.  
  747. ;-------------------------------------------------------------------;
  748. ; This function does nothing                                        ;
  749. ;-------------------------------------------------------------------;
  750. NO_OP:         RET
  751. HELP:          RET
  752.  
  753. ;------------------------------------------------------------------------;
  754. ; This subroutine MAKES A NEW DIRECORY FOR NEW USERS OF MAIN DIRECTORY   ;
  755. ;------------------------------------------------------------------------;
  756.  
  757. NEW_USER:
  758.                CALL HOME_BAR
  759.                CALL MKDIR
  760.                RET
  761.  
  762. ;------------------------------------------------------------------------;
  763. ; This subroutine CHANGES THE DEFAULT MENU FROM SHORT TO LONG            ;
  764. ;------------------------------------------------------------------------;
  765.  
  766. NEW_MENU:
  767.                MOV  DEFAULT_MENU,1         ;DEFAULT TO LONG MENU
  768.                CALL START_DISPLAY          ;AND DISPLAY IT
  769.                RET
  770. ;------------------------------------------------------------------------;
  771. ; This subroutine searches for a directory with a specific first letter. ;
  772. ;------------------------------------------------------------------------;
  773.  
  774. SEARCH:        CMP    BL,'a'                 ;Capitalize if lower case.
  775.                JB     SEARCH_IT
  776.                CMP    BL,'z'
  777.                JA     SEARCH_IT
  778.                AND    BL,5FH
  779. SEARCH_IT:     CMP    BL,'\'                 ;Searching for root?
  780.                JNZ    SEARCH_NAME
  781.                CALL   HOME_BAR               ;If yes, home the bar.
  782.                RET
  783.  
  784. SEARCH_NAME:   CALL   GET_NAME               ;Get current position.
  785.                XOR    DX,DX                  ;Zero out file counter.
  786.                MOV    DI,DIR_NAME            ;Store current position in DI.
  787.                MOV    SI,OFFSET DIRECTORIES  ;Point to top of listing.
  788.                CMP    BYTE PTR [DI],BL       ;Are we currently at a match?
  789.                JNZ    INC_SEARCH             ;If no, start from top.
  790. FIND_START:    INC    DX                     ;Increment count.
  791.                ADD    SI,DIR_RECORD          ;Increment record.
  792.                CMP    SI,END_OFFSET          ;End of tree?
  793.                JAE    SEARCH_BEEP            ;If yes, no match.
  794.                CMP    SI,CUR_RECORD          ;New record?
  795.                JBE    FIND_START             ;If no, find it.
  796.  
  797. NEXT_SEARCH:   XOR    BP,BP                  ;Zero in directory level pointer.
  798. FIND_DASH:     INC    BP
  799.                CMP    BYTE PTR [SI+BP-1],196 ;Is it the dash?
  800.                JNZ    FIND_DASH              ;If no, find it.
  801.  
  802.                CMP    BYTE PTR [SI+BP],BL    ;Got a match?
  803.                JZ     FOUND_IT               ;If yes, process.
  804. INC_SEARCH:    ADD    SI,DIR_RECORD          ;Else, point to next record.
  805.                INC    DX
  806.                CMP    SI,END_OFFSET          ;End of listing?
  807.                JB     NEXT_SEARCH            ;If no, keep searching.
  808. SEARCH_BEEP:   CALL   BEEP                   ;No matches, so beep.
  809.                RET
  810.  
  811. FOUND_IT:      MOV    CX,DIR_COUNT           ;Retrieve directory count.
  812.                SUB    CX,DX                  ;Subtract search count.
  813.                MOV    SEARCH_COUNT,CX        ;And store.
  814.                MOV    CL,ATTR_TREE           ;Turn off bar for now.
  815.                MOV    BAR_ATTRIBUTE,CL
  816.                CALL   END_BAR                ;First move to end.
  817.                JMP    SHORT MARK_IT
  818. NEXT_UP:       CALL   UP_ARROW2              ;Move up to matching filename.
  819. MARK_IT:       DEC    SEARCH_COUNT
  820.                JNZ    NEXT_UP
  821.                MOV    CL,INVERSE             ;Turn bar back on and display.
  822.                MOV    BAR_ATTRIBUTE,CL
  823.                XOR    BP,BP
  824.                CALL   SCROLL_BAR
  825.                RET
  826.  
  827. ;-------------------------------------------------------------------------;
  828. ; This subroutine changes the directory to the one highlighted and exits. ;
  829. ;-------------------------------------------------------------------------;
  830.  
  831. SELECT_DIR:    CALL   GET_NAME
  832.                CALL   NEW_DIR
  833.                CALL   CO1
  834.                CMP    TEMPUS_RETCODE,4     ; pgm NOT fOUND
  835.                JNZ    SELECT_CO
  836.  
  837.                CALL   START_DISPLAY          ;Restore menu.
  838.                CALL   CLEAR_MSG
  839.                MOV    DX,1629H               ;Else, display Warning.
  840.                MOV    SI,OFFSET PATH_ERROR
  841.                CALL   DISPLAY_TEXT
  842.                RET                           ;CAN'T FIND co.com
  843.  
  844. SELECT_CO:     CMP    TEMPUS_RETCODE,3       ; ESC HIT
  845.                JNZ    SELECT_DIR_EXIT
  846.                CALL   START_DISPLAY          ;Restore menu.
  847.                RET
  848. SELECT_DIR_EXIT: JMP    EXIT                   ;Exit.
  849.  
  850. ;-------------------------------------------------------------------------;
  851. ; This subroutine changes the directory to the one highlighted and exits. ;
  852. ;-------------------------------------------------------------------------;
  853.  
  854. CHANGE_DIR:    CALL   GET_NAME
  855.                CALL   NEW_DIR
  856.                JMP    EXIT                   ;Exit.
  857.  
  858. ;----------------------------------------------------;
  859. ; This subroutine renames the highlighted directory. ;
  860. ;----------------------------------------------------;
  861.  
  862. RENAME:        CMP    DOS_VERSION,3          ;Can't rename directories before
  863.                JB     RENAME_ERROR           ; DOS 3.x
  864.                CALL   CLEAR_MSG
  865.                CALL   GET_NAME
  866.                CMP    SI,OFFSET DIRECTORIES  ;Can't rename the root directory.
  867.                JZ     RENAME_ERROR
  868.                CALL   NEW_DIR                ;Change to the requested directory.
  869.                JC     RENAME_READ            ;If nonexistant, reread data.
  870.  
  871.                MOV    DX,162CH               ;Row 22, column 44.
  872.                MOV    SI,OFFSET RENAME_MSG   ;Display rename message.
  873.                CALL   QUERY                  ;Get new name from user.
  874.                JC     RENAME_END             ;If carry, Esc was pressed.
  875.  
  876.                MOV    DX,OFFSET DOT_DOT      ;Change to parent directory.
  877.                CALL   CD
  878.                MOV    DX,DIR_NAME            ;Point to old name.
  879.                MOV    DI,80H
  880.                MOV    AH,56H                 ;Rename.
  881.                INT    21H
  882.                JC     RENAME_ERROR           ;Beep if illegal.
  883. RENAME_READ:   CALL   REREAD                 ;Reread data.
  884. RENAME_END:    CALL   CLEAR_MSG
  885.                RET
  886.  
  887. RENAME_ERROR:  CALL   BEEP                   ;Error exit.
  888.                CALL   CLEAR_MSG
  889.                RET
  890.  
  891. ;-----------------------------------------------------------------------;
  892. ; This subroutine makes a subdirectory under the highlighted directory. ;
  893. ;-----------------------------------------------------------------------;
  894.  
  895. MKDIR:         CALL   CLEAR_MSG
  896.                CALL   GET_NAME
  897.                CALL   NEW_DIR                ;Change to the requested directory.
  898.                JC     MKDIR_READ             ;If nonexistant, reread data.
  899.                MOV    DX,1529H               ;Row 21; column 41.
  900.                MOV    SI,OFFSET PATH_LENGTH  ;Display path message.
  901.                CALL   DISPLAY_TEXT
  902.                CALL   GET_COUNT              ;And the path length.
  903.                CALL   GET_TEXT               ;And end of message.
  904.                CMP    COUNT,63               ;Is it already 63 or more chars?
  905.                JB     MKDIR_QUERY
  906.                CALL   BEEP                   ;If yes, refuse to make directory.
  907.                CALL   DELAY
  908.                JMP    SHORT MKDIR_END
  909.  
  910. MKDIR_QUERY:   MOV    DX,1629H               ;Row 21; column 41.
  911.                MOV    SI,OFFSET MKDIR_MSG1   ;Display path message.
  912.                CALL   DISPLAY_TEXT
  913.                MOV    DX,1729H               ;Point to next row.
  914.                CALL   QUERY                  ;Get name from user.
  915.                JC     MKDIR_END              ;If carry, Esc was pressed.
  916.                MOV    DX,80H
  917.                MOV    AH,39H                 ;Create the directory.
  918.                INT    21H
  919.                JC     MKDIR_ERROR            ;Beep if illegal.
  920. MKDIR_READ:    CALL   REREAD                 ;Reread data.
  921.  
  922. MKDIR_END:     CALL   CLEAR_MSG
  923.                RET
  924.  
  925. MKDIR_ERROR:   CALL   BEEP                   ;Error exit.
  926.                CALL   CLEAR_MSG
  927.                RET
  928.  
  929. ;-------------------------------------------------------;
  930. ; This subroutine removes the highlighted subdirectory. ;
  931. ;-------------------------------------------------------;
  932.  
  933. RMDIR:         CALL   CLEAR_MSG
  934.                CALL   GET_NAME
  935.                MOV    SI,DIR_NAME
  936.                CMP    SI,OFFSET DIRECTORIES    ;Can't remove root directory.
  937.                JNZ    RMDIRG
  938.                JMP    RMDIR_ERROR
  939. RMDIRG:        CMP    BYTE PTR [SI+DIR_RECORD+1],196   ;Can't remove directory
  940.                JNZ    RMDIRD
  941.                JMP    RMDIR_ERROR
  942. RMDIRD:        CALL   NEW_DIR                ;Change to requested directory.
  943.                JNC    RMDIRH                 ;If nonexistant, reread data.
  944.                JMP    RMDIR_READ             ;If nonexistant, reread data.
  945. RMDIRH:        MOV    DX,OFFSET DTA_AREA     ;Restore Disk Transfer Address.
  946.                MOV    AH,1AH
  947.                INT    21H
  948.                CALL   CLEAR_MSG
  949.                CALL   COUNT_THEM             ;Count and display file count.
  950.                CMP    COUNT,0                ;If empty, remove directory.
  951.                JZ     REMOVE
  952.  
  953.                MOV    DX,1729H               ;Else, display file loss Warning.
  954.                MOV    SI,OFFSET RMDIR_MSG
  955.                CALL   DISPLAY_TEXT
  956.                MOV    DX,1829H
  957.                CALL   DISPLAY_TEXT
  958.                CALL   CURSOR_ON
  959.                CALL   READ_KEY               ;Get response.
  960.                CMP    AH,K_Y                 ;If not "Y", exit.
  961.                JNZ    RMDIR_RETURN
  962.                CALL   WRITE_TEXT             ;Else, display it.
  963.                CALL   READ_KEY               ;Get next response.
  964.                CMP    AH,1CH                 ;If not carriage return, exit.
  965.                JNZ    RMDIR_RETURN
  966. ;----------------------------------------------------------------------
  967.                CALL   CLEAR_MSG
  968.                MOV    DX,1629H               ;Else, display file loss Warning.
  969.                MOV    SI,OFFSET RMDIR_MSG2
  970.                CALL   DISPLAY_TEXT
  971.                MOV    DX,1829H
  972.                CALL   DISPLAY_TEXT
  973.                CALL   CURSOR_ON
  974.                CALL   READ_KEY               ;Get response.
  975.                CMP    AH,K_Y                 ;If not "Y", exit.
  976.                JNZ    RMDIR_RETURN
  977. ;----------------------------------------------------------------------
  978.  
  979.                CALL   FIRST_MATCH            ;Else, find all files and delete.
  980.                CALL   DELETE
  981. NEXT_DELETE:   CALL   NEXT_MATCHING
  982.                JC     REMOVE
  983.                CALL   DELETE
  984.                JMP    SHORT NEXT_DELETE
  985.  
  986. REMOVE:        MOV    DX,OFFSET DOT_DOT      ;Move to parent directory.
  987.                CALL   CD
  988.                MOV    DX,DIR_NAME
  989.                MOV    AH,3AH                 ;Remove requested directory.
  990.                INT    21H
  991.                JC     RMDIR_ERROR
  992. RMDIR_READ:    CALL   REREAD                 ;Reread data.
  993. RMDIR_RETURN:  CALL   CLEAR_MSG
  994.                CMP    COUNT,0                ;If empty, remove directory.
  995.                JNZ    RMDIR_EXIT
  996.                MOV    DX,1629H               ;Else, display file loss Warning.
  997.                MOV    SI,OFFSET RMDIR_MSG0
  998.                CALL   DISPLAY_TEXT
  999. RMDIR_EXIT:    RET
  1000.  
  1001. RMDIR_ERROR:   CALL   BEEP                   ;Error exit.
  1002. ;              CALL   CLEAR_MSG
  1003.                RET
  1004.  
  1005. ;------------------------------------------------------------------;
  1006. ; These two subroutines hide and unhide the highlighted directory. ;
  1007. ;------------------------------------------------------------------;
  1008.  
  1009. HIDE_UNHIDE:   CALL   GET_NAME
  1010.                CMP    SI,OFFSET DIRECTORIES  ;Can't hide root directory.
  1011.                JZ     HIDE_ERROR
  1012.                MOV    DX,1629H               ;Row 22; column 41.
  1013.                MOV    SI,OFFSET HIDE_MSG     ;Display hide message.
  1014.                CALL   DISPLAY_TEXT
  1015.                MOV    SI,DIR_NAME
  1016.                CALL   GET_TEXT
  1017.                MOV    BP,2                   ;Hidden attribute.
  1018.                CALL   READ_KEY               ;Get a keystroke.
  1019.                CMP    AH,23H                 ;Is it "H"?
  1020.                JZ     CHANGE_IT              ;If yes, change attribute.
  1021.                XOR    BP,BP                  ;Turn off hidden attribute.
  1022.                CMP    AH,16H                 ;Is it "U"?
  1023.                JNZ    HIDE_END               ;If no, exit.
  1024.  
  1025. CHANGE_IT:     CALL   NEW_DIR
  1026.                JC     HIDE_READ              ;If directory nonexistant, read.
  1027.                MOV    DX,OFFSET DOT_DOT      ;Change to parent directory.
  1028.                CALL   CD
  1029.                MOV    DX,DIR_NAME
  1030.                MOV    CX,BP                  ;Retrieve requested attribute.
  1031.                CALL   CHMOD                  ;And change it.
  1032. HIDE_READ:     CALL   REREAD
  1033.                RET
  1034.  
  1035. HIDE_ERROR:    CALL   BEEP
  1036. HIDE_END:      CALL   CLEAR_MSG
  1037.                RET
  1038.  
  1039. ;--------------------------------------------------------;
  1040. ; This subroutine sets or resets the read-only attribute ;
  1041. ; of all the files of the highlighted directory.         ;
  1042. ;--------------------------------------------------------;
  1043.  
  1044. READ_ONLY:     CALL   GET_NAME
  1045.                CALL   NEW_DIR
  1046.                JC     SET_READ               ;If nonexistant directory, reread.
  1047.                CALL   COUNT_THEM             ;Display file count.
  1048.                CMP    COUNT,0                ;Is directory empty?
  1049.                JZ     READ_END               ;If yes, nothing to mark.
  1050.                MOV    DX,1729H                  ;Row 23; column 41.
  1051.                MOV    SI,OFFSET READ_ONLY_MSG   ;Display read-only message.
  1052.                CALL   DISPLAY_TEXT
  1053.                MOV    STRIP_MASK,11111111xB      ;If read-only request, nothing
  1054.                MOV    ADD_MASK,  00000001B      ; to strip and add bit 1.
  1055.                CALL   READ_KEY
  1056.                CMP    AH,13H                    ;Is it "R"?
  1057.                JZ     DO_READ                   ;If yes, turn on read-only bit.
  1058.                MOV    STRIP_MASK,11111110xB      ;If NOT read-only request, strip
  1059.                MOV    ADD_MASK,0                ; read-only bit and add nothing.
  1060.                CMP    AH,16H                    ;Is it "U"?
  1061.                JNZ    READ_RETURN               ;If no, done here.
  1062.  
  1063. DO_READ:       CALL   DO_ATTRIB              ;Change the attribute.
  1064.                CALL   CLEAR_LINE             ;Clear keystroke prompt line.
  1065.                MOV    DX,1729H               ;Row 23; column 41.
  1066.                MOV    SI,OFFSET HAVE_BEEN    ;Display "have been" message.
  1067.                CALL   DISPLAY_TEXT
  1068.                MOV    SI,OFFSET READ_MSG     ;Display rest of message.
  1069.                JMP    SHORT SET_MSG
  1070.  
  1071. READ_RETURN:   CALL   CLEAR_MSG
  1072.                RET
  1073.  
  1074. READ_END:      CALL   DELAY
  1075.                RET
  1076.  
  1077. SET_READ:      CALL   REREAD
  1078.                RET
  1079.  
  1080. ;------------------------------------------------------;
  1081. ; These two subroutines set and reset the archive bit. ;
  1082. ;------------------------------------------------------;
  1083.  
  1084. SET_RESET:     CALL   GET_NAME
  1085.                CALL   NEW_DIR
  1086.                JC     SET_READ               ;If nonexistant directory, reread.
  1087.                CALL   COUNT_THEM             ;Display file count.
  1088.                CMP    COUNT,0                ;Is directory empty?
  1089.                JZ     SET_END                ;If yes, nothing to mark.
  1090.                MOV    DX,1729H               ;Row 23; column 41.
  1091.                MOV    SI,OFFSET ARCHIVE_MSG  ;Display archive message.
  1092.                CALL   DISPLAY_TEXT
  1093.                MOV    STRIP_MASK,11111111xB   ;If set archive request, nothing
  1094.                MOV    ADD_MASK,  00100000xB   ; to strip and add bit 1.
  1095.                CALL   READ_KEY
  1096.                CMP    AH,1FH                 ;Is it "S"?
  1097.                JZ     DO_ARCHIVE             ;If yes, turn on archive bit.
  1098.                MOV    STRIP_MASK,11011111xB   ;If NOT archive request, strip
  1099.                MOV    ADD_MASK,0             ; archive bit and add nothing.
  1100.                CMP    AH,13H                 ;Is it "R"?
  1101.                JNZ    READ_RETURN            ;If no, done here.
  1102.  
  1103. DO_ARCHIVE:    CALL   DO_ATTRIB              ;Change the attribute.
  1104.                CALL   CLEAR_LINE             ;Clear keystroke prompt line.
  1105.                MOV    DX,1729H               ;Row 23; column 41.
  1106.                MOV    SI,OFFSET HAVE_BEEN    ;Display "have been" message.
  1107.                CALL   DISPLAY_TEXT
  1108.  
  1109. SET_MSG:       CMP    ADD_MASK,0             ;If add nothing, display strip
  1110.                JZ     DISPLAY_MSG            ; message.
  1111.                ADD    SI,4                   ;Else, display bit on message.
  1112. DISPLAY_MSG:   CALL   GET_TEXT
  1113. SET_END:       CALL   DELAY                  ;Wait for keystroke, then remove
  1114.                RET                           ; message.
  1115.  
  1116. ;-----------------------------------------------;
  1117. ; This subroutine displays the file count and   ;
  1118. ; displacement of the highlighted subdirectory. ;
  1119. ;-----------------------------------------------;
  1120.  
  1121. FILE_SUM:      CALL   CLEAR_MSG              ;CLEAR PREV MSG
  1122.                CALL   GET_NAME
  1123.                CALL   NEW_DIR                ;Change to requested directory.
  1124. ;              JC     REREAD                 ;If nonexistant, reread data.
  1125.  
  1126.                MOV    DX,OFFSET DTA_AREA     ;Restore Disk Transfer Address.
  1127.                MOV    AH,1AH
  1128.                INT    21H
  1129.  
  1130.                CALL   COUNT_THEM             ;Get file count and displacement.
  1131. ;              CALL   DELAY                  ;Display count until keystroke.
  1132.                RET
  1133.  
  1134. ;-------------------------------------------------------------------;
  1135. ; This subroutine rereads the directory tree information from disk. ;
  1136. ;-------------------------------------------------------------------;
  1137.  
  1138. REREAD:        MOV    PAGE_END,21*160+PAGE_START ;Reset default values.
  1139.                MOV    DIR_COUNT,1
  1140.                CALL   CLEAR_MSG              ;Clear the last message.
  1141.                MOV    DX,162DH               ;Row 22, column 45.
  1142.                MOV    SI,OFFSET LOADING      ;Display loading message.
  1143.                CALL   DISPLAY_TEXT
  1144.                CALL   READ_DATA              ;Read the data.
  1145.                CALL   FORMAT_IT              ;Construct new tree.
  1146.                CALL   START_DISPLAY          ;Display menu.
  1147.                CALL   CLEAR_MSG              ;Clear sorting message.
  1148.                XOR    BP,BP                  ;Update directory display.
  1149.                CALL   SCROLL
  1150.                MOV    SI,PAGE_END            ;Move bar if below directory
  1151.                SUB    SI,160                 ; display.
  1152.                CMP    SI,LINE
  1153.                JA     REREAD_END
  1154.                CALL   MOVE_BAR
  1155. REREAD_END:    RET
  1156. ;-----------------------------------------------;
  1157. ; This subroutine SETS Backup/Restore parameters;
  1158. ;-----------------------------------------------;
  1159.  
  1160. B_R_OPTIONS:
  1161.               CALL BRDRIVE
  1162.               CALL BRPATH
  1163.               CALL BROPTIONS
  1164.               RET
  1165.  
  1166. ;-----------------------------------------------;
  1167. ; This subroutine SETS Backup/Restore DRIVE     ;
  1168. ;-----------------------------------------------;
  1169.  
  1170. BRDRIVE:
  1171.                CALL CLEAR_MSG
  1172.                MOV  DX,162CH                    ;Row 22, column 44.
  1173.                MOV  SI,OFFSET BRDRIVE_MSG
  1174.                MOV  DI,80H                      ;INPUT SAVE
  1175.                MOV  CX,2                        ;NO INPUT CHARS ALLOWED
  1176.                CALL BRQUERY
  1177.                JC   BRDRIVE_RET              ;If carry, Esc was pressed.
  1178.                MOV  SI,80H                      ;INPUT SAVE
  1179.                MOV  AL,BYTE PTR [SI]
  1180.                AND  AL,5FH                      ;CAPITALIZE
  1181.                CMP  AL,'A'
  1182.                JB   BRDRIVE_RET
  1183.                CMP  AL,'Z'
  1184.                JA   BRDRIVE_RET
  1185.                MOV  CX,1                        ;NO INPUT CHARS ALLOWED
  1186.                MOV  DI,OFFSET ODRIVE
  1187.                REP    MOVSB
  1188. BRDRIVE_RET:
  1189.                CLC
  1190. ;              CALL   CLEAR_MSG
  1191.                CALL   START_DISPLAY
  1192.                RET
  1193. ;-----------------------------------------------;
  1194. ; This subroutine SETS Backup/Restore PATH      ;
  1195. ;-----------------------------------------------;
  1196.  
  1197. BRPATH:
  1198.                CALL CLEAR_MSG
  1199.                MOV  DX,162CH                    ;Row 22, column 44.
  1200.                MOV  SI,OFFSET BRPATH_MSG        ;MSG
  1201.                MOV  DI,80H                      ;INPUT SAVE
  1202.                MOV  CX,12                       ;NO INPUT CHARS ALLOWED
  1203.                CALL BRQUERY
  1204.                JC   BRPATH_RET               ;If carry, Esc was pressed.
  1205.                MOV  CX,12                       ;NO INPUT CHARS ALLOWED
  1206.                MOV  SI,80H                      ;INPUT SAVE
  1207.                MOV  DI,OFFSET OPATH
  1208.                REP    MOVSB
  1209. BRPATH_RET:
  1210.                CLC
  1211. ;              CALL   CLEAR_MSG
  1212.                CALL   START_DISPLAY
  1213.                RET
  1214. ;-----------------------------------------------;
  1215. ; This subroutine SETS Backup/Restore OPTIONS   ;
  1216. ;-----------------------------------------------;
  1217.  
  1218. BROPTIONS:
  1219.                 CALL CLEAR_MSG
  1220.                 MOV  DX,162CH                    ;Row 22, column 44.
  1221.                 MOV  SI,OFFSET BROPTIONS_MSG     ;MSG
  1222.                 MOV  DI,80H                      ;INPUT SAVE
  1223.                 MOV  CX,18                       ;NO INPUT CHARS ALLOWED
  1224.                 CALL BRQUERY
  1225.                 JC   BROPTIONS_RET           ;If carry, Esc was pressed.
  1226.                 MOV  CX,18                       ;NO INPUT CHARS ALLOWED
  1227.                 MOV  SI,80H                      ;INPUT SAVE
  1228.                 MOV  DI,OFFSET OOPTIONS
  1229.                 REP    MOVSB
  1230. BROPTIONS_RET:
  1231.                 CLC
  1232. ;               CALL   CLEAR_MSG
  1233.                 CALL   START_DISPLAY
  1234.                 RET
  1235.  
  1236. ;-----------------------------------------------;
  1237. ; This subroutine spawns COMMAND COM FOR BACKUP ;
  1238. ;-----------------------------------------------;
  1239.  
  1240. BACKUP:
  1241.                MOV    USE_DIR_EQ," "
  1242.                MOV    AX,CUR_OFFSET
  1243.                MOV    CUR_OFFSET_SAVE,AX        ;SAVE OFFSET
  1244.                MOV    AX,LINE
  1245.                MOV    LINE_SAVE,AX              ;SAVE LINE
  1246.                MOV    T_CLUST_COUNT_1_2MEG,0    ;And cluster counter.
  1247.                MOV    T_CLUST_COUNT_1_4MEG,0    ;And cluster counter.
  1248.                MOV    T_CLUST_COUNT_360K,0      ;And cluster counter.
  1249.                MOV    AT_LAST_LINE,"0"
  1250.  
  1251.                CALL   FILE_SUM               ;WRITE NO FILES
  1252.                MOV    AX,CLUST_COUNT_1_2MEG     ;GET CUR Cluster counter.
  1253.                MOV    T_CLUST_COUNT_1_2MEG,AX   ;SAVE IN TOTAL
  1254.                MOV    AX,CLUST_COUNT_1_4MEG     ;GET CUR Cluster counter.
  1255.                MOV    T_CLUST_COUNT_1_4MEG,AX   ;SAVE IN TOTAL
  1256.                MOV    AX,CLUST_COUNT_360K       ;GET CUR Cluster counter.
  1257.                MOV    T_CLUST_COUNT_360K,AX     ;SAVE IN TOTAL
  1258.                CALL   GET_NAME
  1259.                MOV    BX,CUR_LEVEL           ;GET LEVEL OF CUR DIR
  1260.                MOV    CUR_LEVEL_SAVE,BX      ;SAVE IT FOR LATER
  1261.                CALL   NEW_DIR                ;Change the default directory.
  1262.                CMP    USE_DIRECTORY,32       ;IS THERE SPECIAL DIRECTORY NAME
  1263.                JE     BACKUP_COUNT
  1264.                MOV    SI,DIR_NAME            ;LOAD NAME USER POINTING AT
  1265.                MOV    DI,OFFSET USE_DIRECTORY ;LOAD SPEC NAME
  1266.                MOV    CX,11                 ; COUNT FOR COMPARE
  1267.                REPE   CMPSB
  1268.                JE     BACKUP_EQU            ; NOT EQUAL BYPASS
  1269.                CMP    BYTE PTR [DI],32      ; HIT BLANKS
  1270.                JNZ    BACKUP_COUNT          ; NOT EQUAL BYPASS
  1271.                CMP    BYTE PTR [SI],00      ; HIT BLANKS
  1272.                JNZ    BACKUP_COUNT          ; NOT EQUAL BYPASS
  1273. BACKUP_EQU:    MOV    USE_DIR_EQ,"="        ; SAY EQUAL
  1274.                MOV    T_CLUST_COUNT_1_2MEG,0    ;RESET cluster counter.
  1275.                MOV    T_CLUST_COUNT_1_4MEG,0    ;RESET cluster counter.
  1276.                MOV    T_CLUST_COUNT_360K,0      ;RESET cluster counter.
  1277. BACKUP_COUNT:
  1278.                CALL   DN_ARROW2             ; DOWN ONE
  1279.                CMP    AT_LAST_LINE,"="         ;AT LIST LINE THEN OUT
  1280.                JE     BACKUP_COUNT_END         ;DONE IS LAST ENTRY
  1281.                CALL   FILE_SUM               ;WRITE NO FILES
  1282.                MOV    AX,CUR_LEVEL           ;GET LEVEL OF CUR DIR
  1283.                CMP    AX,CUR_LEVEL_SAVE      ;LOAD ORIG LEVEL
  1284.                JBE    BACKUP_COUNT_END
  1285.                MOV    AX,CLUST_COUNT_1_2MEG     ;GET CUR Cluster counter.
  1286.                ADD    T_CLUST_COUNT_1_2MEG,AX   ;SAVE IN TOTAL
  1287.                MOV    AX,CLUST_COUNT_1_4MEG     ;GET CUR Cluster counter.
  1288.                ADD    T_CLUST_COUNT_1_4MEG,AX   ;SAVE IN TOTAL
  1289.                MOV    AX,CLUST_COUNT_360K       ;GET CUR Cluster counter.
  1290.                ADD    T_CLUST_COUNT_360K,AX     ;SAVE IN TOTAL
  1291.                JMP    BACKUP_COUNT           ;DO AGAIN
  1292.  
  1293. BACKUP_COUNT_END:
  1294.                MOV    AX,CUR_OFFSET_SAVE
  1295.                MOV    CUR_OFFSET,AX             ;RESTORE OFFSET
  1296.                MOV    AX,LINE_SAVE
  1297.                MOV    LINE,AX                   ;RESTORE LINE
  1298.                CALL   START_DISPLAY          ;Restore menu.
  1299.                CALL   UPDATE_SCREEN
  1300.                MOV    DISKS_1_2MEG,0
  1301.                XOR    DX,DX                  ;Zero in high half.
  1302.                MOV    AX,T_CLUST_COUNT_1_2MEG  ;CNT OF 1.2MEG CLUSTERS USED
  1303.                DIV    CLUSTERS_1_2MEG        ;Divide to get NO DISKS
  1304.                OR     DX,DX                  ;If remainder, increment count.
  1305.                JZ     NO_REM_1_2MEG_T
  1306.                INC    DISKS_1_2MEG
  1307. NO_REM_1_2MEG_T: ADD    DISKS_1_2MEG,AX      ;Add DISK count.
  1308.  
  1309.                MOV    DISKS_1_4MEG,0
  1310.                XOR    DX,DX                  ;Zero in high half.
  1311.                MOV    AX,T_CLUST_COUNT_1_4MEG  ;CNT OF 1.24EG CLUSTERS USED
  1312.                DIV    CLUSTERS_1_4MEG        ;Divide to get NO DISKS
  1313.                OR     DX,DX                  ;If remainder, increment count.
  1314.                JZ     NO_REM_1_4MEG_T
  1315.                INC    DISKS_1_4MEG
  1316. NO_REM_1_4MEG_T: ADD    DISKS_1_4MEG,AX      ;Add DISK count.
  1317.  
  1318.                MOV    DISKS_360K,0
  1319.                XOR    DX,DX                  ;Zero in high half.
  1320.                MOV    AX,T_CLUST_COUNT_360K    ;CNT OF 360K CLUSTERS USED
  1321.                DIV    CLUSTERS_360K          ;Divide to get NO DISKS
  1322.                OR     DX,DX                  ;If remainder, increment count.
  1323.                JZ     NO_REM_360K_T
  1324.                INC    DISKS_360K
  1325. NO_REM_360K_T: ADD    DISKS_360K,AX      ;Add DISK count.
  1326.  
  1327.                CALL   CLEAR_MSG
  1328.                MOV    DX,1529H               ;Row 22; column 41.
  1329.                CALL   SET_CURSOR
  1330.                MOV    SI,OFFSET FORMAT_MSG   ;DISPLAY FORMAT MSG
  1331.                CALL   GET_TEXT
  1332.                MOV    DX,1629H               ;Row 22; column 41.
  1333.                CALL   SET_CURSOR
  1334.                MOV    SI,OFFSET BACKUP_USES  ;DISPLAY MESSAGE
  1335.                CALL   GET_TEXT
  1336.                MOV    AX,DISKS_1_2MEG
  1337.                MOV    COUNT,AX               ;1.2MEG COUNT
  1338.                CALL   GET_COUNT              ;Display count.
  1339.                MOV    SI,OFFSET BACKUP_USES_1_2MEG ;DISPLAY MESSAGE
  1340.                CALL   GET_TEXT
  1341.  
  1342.                MOV    DX,1729H               ;Row 22; column 41.
  1343.                CALL   SET_CURSOR
  1344.                MOV    SI,OFFSET BACKUP_USES  ;DISPLAY MESSAGE
  1345.                CALL   GET_TEXT
  1346.                MOV    AX,DISKS_1_4MEG
  1347.                MOV    COUNT,AX               ;1.2MEG COUNT
  1348.                CALL   GET_COUNT              ;Display count.
  1349.                MOV    SI,OFFSET BACKUP_USES_1_4MEG ;DISPLAY MESSAGE
  1350.                CALL   GET_TEXT
  1351.  
  1352.                MOV    DX,1829H               ;Row 23; column 41.
  1353.                CALL   SET_CURSOR
  1354.                MOV    SI,OFFSET BACKUP_USES  ;DISPLAY MESSAGE
  1355.                CALL   GET_TEXT
  1356.                MOV    AX,DISKS_360K
  1357.                MOV    COUNT,AX               ;360K COUNT
  1358.                CALL   GET_COUNT              ;Display count.
  1359.                MOV    SI,OFFSET BACKUP_USES_360K  ;DISPLAY MESSAGE
  1360.                CALL   GET_TEXT
  1361. BACKUP_READ:   CALL   READ_KEY
  1362.                CMP    AH,K_ESC
  1363.                JNE    BACKUP_NO_ESC
  1364.                JMP    BACKUP_EXIT
  1365. BACKUP_NO_ESC: CMP    AH,K_N
  1366.                JE     FORMAT_NONE
  1367.                CMP    AH,K_Y
  1368.                JE     FORMAT_SOME
  1369.                CMP    AH,K_ENTER
  1370.                JE     FORMAT_NONE
  1371.                JMP    BACKUP_READ
  1372. ;----------------------------------------------------------------------
  1373. FORMAT_SOME:
  1374.                CALL   CLS                    ;Clear screen.
  1375.                MOV    SI,OFFSET PARA_FORMAT  ; NAME OF PGM
  1376.                MOV    DI,OFFSET PARA_BR+1    ; MOVE TO
  1377.                CALL   MOVE_TEXT
  1378.                MOV    CX,2                   ;NO INPUT CHARS ALLOWED
  1379.                MOV    SI,OFFSET ODRIVE
  1380.                REP    MOVSB
  1381.                MOV    BYTE PTR [DI],13
  1382.                MOV    SI,OFFSET PARA_BR+1    ; MOVE TO
  1383.                SUB    DI,SI
  1384.                MOV    AX,DI
  1385.                MOV    PARA_BR,AL             ;STORE LENGTH
  1386.                MOV    BX,OFFSET PARA_BR      ;LOAD OUT PARM FOR CHILD
  1387.                MOV    WORD PTR COM_LINE_PTR,BX
  1388.                CALL   COMMAND_COM           ;DO FORMAT
  1389. FORMAT_NONE:
  1390.                MOV    PARA_ADD,"  "
  1391.                MOV    AT_LAST_LINE,0
  1392.                CALL   FILE_SUM                  ;WRITE NO FILES
  1393. BACKUP_LOOP:   CMP    AT_LAST_LINE,"="         ;AT LAST LINE THEN OUT
  1394.                JNE    BACKUP_NO_EQ
  1395.                JMP    BACKUP_EXIT
  1396. BACKUP_NO_EQ:  CMP    USE_DIR_EQ,"="         ; EQUAL SPECIAL
  1397.                JNE    BACKUP_CD                ;DONE IS LAST ENTRY
  1398.                CALL   DN_ARROW2             ; DOWN ONE
  1399.                CMP    AT_LAST_LINE,"="         ;AT LAST LINE THEN OUT
  1400.                JE     BACKUP_EXIT
  1401.  
  1402. BACKUP_CD:     MOV    SI,OFFSET PARA_BACKUP  ; NAME OF PGM
  1403.                MOV    DI,OFFSET PARA_BR+1    ; MOVE TO
  1404.                CALL   MOVE_TEXT
  1405.                MOV    AH,19H                 ;Get default drive and save.
  1406.                INT    21H
  1407.                ADD    AL,'A'                 ;CONVERT TO ASCII DRIVE
  1408.                STOSB
  1409.                MOV    AL,':'                 ;CONVERT TO ASCII DRIVE
  1410.                STOSB
  1411.                MOV    CX,12                  ;NO INPUT CHARS ALLOWED
  1412.                MOV    SI,OFFSET OPATH
  1413.                REP    MOVSB
  1414.                MOV    BYTE PTR [DI],32
  1415.                INC    DI
  1416.                MOV    CX,2                   ;NO INPUT CHARS ALLOWED
  1417.                MOV    SI,OFFSET ODRIVE
  1418.                REP    MOVSB
  1419.                MOV    BYTE PTR [DI],32
  1420.                INC    DI
  1421.                MOV    CX,18                  ;NO INPUT CHARS ALLOWED
  1422.                MOV    SI,OFFSET OOPTIONS
  1423.                REP    MOVSB
  1424.                CMP    USE_DIR_EQ,"="         ; IS SPECIAL DIR
  1425.                JNE    BACKUP_NO_SPEC
  1426.                MOV    BYTE PTR [DI],32
  1427.                INC    DI
  1428.                MOV    CX,2                   ;ADD /A TO PARMS
  1429.                MOV    SI,OFFSET PARA_ADD
  1430.                REP    MOVSB
  1431. BACKUP_NO_SPEC:
  1432.                MOV    BYTE PTR [DI],13
  1433.                MOV    SI,OFFSET PARA_BR+1    ; MOVE TO
  1434.                SUB    DI,SI
  1435.                MOV    AX,DI
  1436.                MOV    PARA_BR,AL             ;STORE LENGTH
  1437.                MOV    BX,OFFSET PARA_BR      ;LOAD OUT PARM FOR CHILD
  1438.                MOV    WORD PTR COM_LINE_PTR,BX
  1439.                CALL   CLS                    ;Clear screen.
  1440.                CALL   COMMAND_COM           ;DO BACKUP
  1441.                MOV    PARA_ADD,"A/"
  1442.                CMP    USE_DIR_EQ,"="         ; IS SPECIAL DIR
  1443.                JNE    BACKUP_EXIT
  1444.                JMP    BACKUP_LOOP
  1445.  
  1446. BACKUP_EXIT:   MOV    AX,CUR_OFFSET_SAVE
  1447.                MOV    CUR_OFFSET,AX             ;RESTORE OFFSET
  1448.                MOV    AX,LINE_SAVE
  1449.                MOV    LINE,AX                   ;RESTORE LINE
  1450.                CALL   CLS                    ;Clear screen.
  1451.                CALL   START_DISPLAY          ;Restore menu.
  1452.                CALL   FILE_SUM                  ;WRITE NO FILES
  1453.                RET
  1454.  
  1455. ;-----------------------------------------------;
  1456. ; This subroutine spawns COMMAND COM FOR RESTORE;
  1457. ;-----------------------------------------------;
  1458.  
  1459. RESTORE:
  1460.                CALL   GET_NAME               ;Change the default directory.
  1461.                CALL   NEW_DIR                ;Change the default directory.
  1462.  
  1463.                MOV    SI,OFFSET PARA_RESTORE ; NAME OF PGM
  1464.                MOV    DI,OFFSET PARA_BR+1    ; MOVE TO
  1465.                CALL   MOVE_TEXT
  1466.                MOV    CX,2                   ;NO INPUT CHARS ALLOWED
  1467.                MOV    SI,OFFSET ODRIVE
  1468.                REP    MOVSB
  1469.                MOV    BYTE PTR [DI],32
  1470.                INC    DI
  1471.                MOV    CX,12                  ;NO INPUT CHARS ALLOWED
  1472.                MOV    SI,OFFSET OPATH
  1473.                REP    MOVSB
  1474.                MOV    BYTE PTR [DI],32
  1475.                INC    DI
  1476.                MOV    CX,18                  ;NO INPUT CHARS ALLOWED
  1477.                MOV    SI,OFFSET OOPTIONS
  1478.                REP    MOVSB
  1479.                MOV    BYTE PTR [DI],13
  1480.                MOV    SI,OFFSET PARA_BR+1    ; MOVE TO
  1481.                SUB    DI,SI
  1482.                MOV    AX,DI
  1483.                MOV    PARA_BR,AL             ;STORE LENGTH
  1484.                MOV    BX,OFFSET PARA_BR      ;LOAD OUT PARM FOR CHILD
  1485.                MOV    WORD PTR COM_LINE_PTR,BX
  1486.                CALL   COMMAND_COM           ;DO BACKUP
  1487.  
  1488. RESTORE_EXIT:
  1489.                CALL   CLS                    ;Clear screen.
  1490.                CALL   START_DISPLAY          ;Restore menu.
  1491.                RET
  1492.  
  1493. ;---------------------------------------------;
  1494. ; This subroutine spawns CO. WITH COMMAND.COM ;
  1495. ;---------------------------------------------;
  1496. CO:            MOV    SI,OFFSET PARAMETER    ;LOAD OUT PARM FOR CHILD
  1497.                MOV    DI,OFFSET PARA_BR+1    ; MOVE TO
  1498.                CALL   MOVE_TEXT
  1499.                MOV    BYTE PTR [DI],13
  1500.                MOV    SI,OFFSET PARA_BR+1    ; MOVE TO
  1501.                SUB    DI,SI
  1502.                MOV    AX,DI
  1503.                MOV    PARA_BR,AL             ;STORE LENGTH
  1504.                MOV    BX,OFFSET PARA_BR      ;LOAD OUT PARM FOR CHILD
  1505.                MOV    WORD PTR COM_LINE_PTR,BX
  1506.  
  1507.                CALL   COMMAND_COM           ;DO BACKUP
  1508.                CALL   CLS                    ;Clear screen.
  1509.                CALL   START_DISPLAY          ;Restore menu.
  1510.                RET
  1511.  
  1512. ;-------------------------------------------------------------------;
  1513. ; This function EXITS TO DOS                                        ;
  1514. ;-------------------------------------------------------------------;
  1515. EXIT_DOS:
  1516.                CALL   CLS                    ;Clear screen.
  1517.                CALL   CURSOR_ON              ;Turn it on.
  1518.                CALL   CURSOR_ON              ;Turn it on.
  1519.                CALL   CURSOR_ON              ;Turn it on.
  1520.                XOR    DX,DX                  ;Home cursor.
  1521.                CALL   SET_CURSOR
  1522.                MOV    PARA_BR,00
  1523.                MOV    BX,OFFSET PARA_BR      ;LOAD OUT PARM FOR CHILD
  1524.                MOV    WORD PTR COM_LINE_PTR,BX
  1525.                CALL   COMMAND_COM           ;DO BACKUP
  1526.                CALL   CLS                    ;Clear screen.
  1527.                CALL   CURSOR_OFF             ;Turn it on.
  1528.                CALL   START_DISPLAY          ;Restore menu.
  1529.                RET
  1530.  
  1531. COMMAND_COM:   CALL   GET_NAME
  1532.                CALL   NEW_DIR                ;Change the default directory.
  1533.                MOV    BX,1000H               ;Shrink memory down to one segment.
  1534.                MOV    AH,4AH
  1535.                INT    21H
  1536.  
  1537.                PUSH   DS                     ;Save segment registers.
  1538.                PUSH   ES
  1539.                CALL   CLS                    ;Clear screen.
  1540.                CLI
  1541.                MOV    STACK_SEG,SS           ;Save stack segment and pointer.
  1542.                MOV    STACK_PTR,SP
  1543.                STI
  1544.  
  1545.                MOV    WORD PTR COM_LINE_PTR + 2,DS
  1546.                MOV    AX,DS:[2CH]           ;Retrieve environment segment.
  1547.                MOV    ENVIRONMENT,AX        ;And put in paramter block.
  1548.                MOV    DS,AX                 ;And data segment.
  1549.                XOR    AX,AX                  ;Zero out pointer.
  1550. FIND_COMSPEC:  MOV    SI,AX                  ;Point to environment offset.
  1551.                INC    AX                     ;Next offset.
  1552.                CMP    WORD PTR[SI+1],0000H   ;END OF ENVIRONMENT?
  1553.                JE     NOCOMSPEC              ;YES
  1554.                MOV    DI,OFFSET COMSPEC      ;Find "Comspec=".
  1555.                MOV    CX,8
  1556.                REP    CMPSB
  1557.                JNZ    FIND_COMSPEC
  1558.                MOV    DX,SI                  ;What follows is Command.com path.
  1559.  
  1560.                MOV    BX,OFFSET ENVIRONMENT  ;Point to parameter block.
  1561.                MOV    AX,4B00H               ;Execute.
  1562.                INT    21H
  1563.  
  1564.                MOV    AX,4D00H               ;Get Return Code
  1565.                INT    21H
  1566.                MOV    DI,OFFSET TEMPUS_RETCODE ;Load Return Code Addr
  1567.                STOSB
  1568.  
  1569. NOCOMSPEC:     CLI
  1570.                MOV    SP,CS:STACK_PTR        ;Restore stack segment and pointer.
  1571.                MOV    SS,CS:STACK_SEG
  1572.                STI
  1573.                POP    ES                     ;Restore segment registers.
  1574.                POP    DS
  1575.  
  1576.                MOV    DX,80H                 ;Restore Disk Transfer Address.
  1577.                MOV    AH,1AH
  1578.                INT    21H
  1579.                MOV    BX,2000H               ;Restore dual memory segments.
  1580.                MOV    AH,4AH
  1581.                INT    21H
  1582.                RET
  1583.  
  1584. ;-----------------------------------------------;
  1585. ; This subroutine spawns CO.                    ;
  1586. ;-----------------------------------------------;
  1587.  
  1588. CO1:           CALL   GET_NAME
  1589.                CALL   NEW_DIR                ;Change the default directory.
  1590.                MOV    BX,1000H               ;Shrink memory down to one segment.
  1591.                MOV    AH,4AH
  1592.                INT    21H
  1593.  
  1594.                PUSH   DS                     ;Save segment registers.
  1595.                PUSH   ES
  1596.                CALL   CLS                    ;Clear screen.
  1597.                CLI
  1598.                MOV    STACK_SEG,SS           ;Save stack segment and pointer.
  1599.                MOV    STACK_PTR,SP
  1600.                STI
  1601.  
  1602.                MOV    DI,OFFSET PATH_FOR_PGM        ;MOVE WORK AREA
  1603.                MOV    AL,DEFAULT_DRIVE              ;DEFAULT DRIVE
  1604.                ADD    AL,'A'                        ;MAKE ASCII
  1605.                STOSB
  1606.                MOV    AL,':'
  1607.                STOSB
  1608.                MOV    SI,OFFSET DEFAULT_DIR         ;DEFAULT DIR
  1609.                CALL   MOVE_TEXT                     ;
  1610.                MOV    SI,OFFSET LOAD_NAME_CO        ;DEFAULT DIR
  1611.                CALL   MOVE_TEXT                     ;
  1612.                MOV    BYTE PTR [DI],00              ;END OF NAME
  1613.                INC    DI                            ;
  1614.  
  1615.                MOV    WORD PTR COM_LINE_PTR + 2,DS
  1616.                MOV    BX,OFFSET PARAMETER    ;LOAD OUT PARM FOR CHILD
  1617.                MOV    WORD PTR COM_LINE_PTR,BX
  1618.                MOV    AX,DS:[2CH]          ;Retrieve environment segment.
  1619.                MOV    ENVIRONMENT,AX       ;And put in paramter block.
  1620.                MOV    DS,AX                ;And data segment.
  1621.                XOR    AX,AX                ;Zero out pointer.
  1622. FIND_COMSPEC1: MOV    SI,AX                ;Point to environment offset.
  1623.                INC    AX                   ;Next offset.
  1624.                MOV    BX,WORD PTR[SI+1]    ;
  1625.                CMP    BX,0000H             ;END OF ENVIRONMENT?
  1626.                JNZ    CONTPATH               ;YES
  1627.  
  1628.                JMP    PATH_CONT
  1629.  
  1630. CONTPATH:      MOV    DI,OFFSET PATH       ;Find "PATH="
  1631.                MOV    CX,6
  1632.                REP    CMPSB
  1633.                JNZ    FIND_COMSPEC1
  1634. PATH_CONT:                                ;What follows is PATH NAMES
  1635.                MOV    AX,DS                  ;POINT TO CS
  1636.                MOV    BX,SI                  ;POINT TO CS
  1637.                MOV    DS,CS                  ;POINT TO CS
  1638.                MOV    SAVE_DS_PATH,AX      ;SAVE ADDR OF PATH
  1639.                MOV    SAVE_SI_PATH,BX      ;SAVE ADDR OF PATH
  1640. TRY_AGAIN:     MOV    DS,CS                  ;POINT TO CS
  1641.                MOV    WORD PTR COM_LINE_PTR + 2,CS
  1642.                MOV    BX,OFFSET PARM_SAVE_LGTH  ;LOAD OUT PARM FOR CHILD
  1643.                MOV    WORD PTR COM_LINE_PTR,BX
  1644.                MOV    DX,OFFSET PATH_FOR_PGM    ;Point to PGM NAME
  1645.  
  1646.                MOV    BX,OFFSET ENVIRONMENT  ;Point to parameter block.
  1647.                MOV    AX,4B00H               ;Execute.
  1648.                INT    21H
  1649.                JNC    CO_FOUND
  1650.  
  1651.                PUSH   DS
  1652.                PUSH   SI
  1653.                MOV    DS,CS                         ;POINT TO CS
  1654.                MOV    DI,OFFSET PATH_FOR_PGM        ;MOVE WORK AREA
  1655.                MOV    SI,SAVE_SI_PATH
  1656.                MOV    DS,SAVE_DS_PATH
  1657.                LODSB                                ;LOAD PATH CHAR
  1658.                DEC    SI
  1659.                CMP    AL,00
  1660.                JNZ    PATH_LOOP
  1661.                POP    SI
  1662.                POP    DS
  1663.                MOV    DS,CS                         ;POINT TO CS
  1664.                MOV    TEMPUS_RETCODE,4              ;SET RETURN CODE
  1665.                JMP    CO1_RETURN
  1666. PATH_LOOP:     LODSB                                ;LOAD PATH CHAR
  1667.                CMP    AL,';'
  1668.                JE     ADD_CO_NAME_1
  1669.                CMP    AL,00
  1670.                JE     ADD_CO_NAME
  1671. CO_NEXT:       STOSB                                ;LOAD PATH CHAR
  1672.                JMP    PATH_LOOP
  1673. ADD_CO_NAME:
  1674.                DEC    SI                     ;KEEP LAST CHAR ; OR x'00'
  1675. ADD_CO_NAME_1:
  1676.                MOV    AX,DS                  ;SAVE DS
  1677.                MOV    BX,SI                  ;SAVE SI
  1678.                MOV    DS,CS                  ;USE CS
  1679.                MOV    SAVE_DS_PATH,AX      ;SAVE ADDR OF PATH
  1680.                MOV    SAVE_SI_PATH,BX      ;SAVE ADDR OF PATH
  1681.                MOV    SI,OFFSET LOAD_NAME_CO        ;ADD CO NAME
  1682.                CALL   MOVE_TEXT                     ;
  1683.                MOV    BYTE PTR [DI],00              ;END OF NAME
  1684.                INC    DI                            ;
  1685.                POP    SI
  1686.                POP    DS
  1687.                JMP    TRY_AGAIN
  1688.  
  1689. CO_FOUND:      MOV    AX,4D00H               ;Get Return Code
  1690.                INT    21H
  1691.                MOV    DI,OFFSET TEMPUS_RETCODE ;Load Return Code Addr
  1692.                STOSB
  1693.  
  1694. CO1_RETURN:    CLI
  1695.                MOV    SP,CS:STACK_PTR        ;Restore stack segment and pointer.
  1696.                MOV    SS,CS:STACK_SEG
  1697.                STI
  1698.                POP    ES                     ;Restore segment registers.
  1699.                POP    DS
  1700.  
  1701.                MOV    DX,80H                 ;Restore Disk Transfer Address.
  1702.                MOV    AH,1AH
  1703.                INT    21H
  1704.                MOV    BX,2000H               ;Restore dual memory segments.
  1705.                MOV    AH,4AH
  1706.                INT    21H
  1707.                CALL   CLS                    ;Clear screen.
  1708. ;              CALL   START_DISPLAY          ;Restore menu.
  1709.                RET
  1710.  
  1711. ;--------------------------------------------------------------------------;
  1712. ; These six subroutines control the bar and page of the directory listing. ;
  1713. ;--------------------------------------------------------------------------;
  1714.  
  1715. UP_ARROW:
  1716. ;----------------FW----------------------------------------------
  1717.                MOV    BX,DIR_COUNT
  1718.                CMP    BX,21
  1719.                JA     UP_ARROW1
  1720.                MOV    BX,LINE
  1721.                ADD    BX,-160                ;Move bar up one line.
  1722.                CMP    USE_DIRECTORY,32       ;IS THERE SPECIAL DIRECTORY NAME
  1723.                JE     UP_ARROW_REG
  1724.                CMP    BX,PAGE_START          ;START OF LIST  \ROOT +1
  1725.                JA     UP_ARROW2
  1726.                JMP    END_BAR
  1727. UP_ARROW_REG:  CMP    BX,PAGE_START-160      ;START OF LIST  \ROOT
  1728.                JA     UP_ARROW2
  1729.                JMP    END_BAR
  1730. UP_ARROW1:     MOV    BX,CUR_OFFSET
  1731.                ADD    BX,-160                ;Move bar up one line.
  1732.                CMP    BX,OFFSET DIRECTORIES  ;START OF LIST
  1733.                JAE    UP_ARROW2
  1734.                MOV    BX,LINE
  1735.                ADD    BX,-160                ;Move bar up one line.
  1736.                CMP    USE_DIRECTORY,32       ;IS THERE SPECIAL DIRECTORY NAME
  1737.                JE     UP_ARROW_REG
  1738.                CMP    BX,PAGE_START          ;START OF LIST  \ROOT +1
  1739.                JA     UP_ARROW2
  1740.                JMP    END_BAR
  1741. ;----------------------------------------------------------------
  1742. UP_ARROW2:     MOV    BP,-160                ;Move bar up one line.
  1743.                CALL   SCROLL_BAR
  1744.                CALL   SCROLL_TOP             ;FW TOP CHECK
  1745.                RET
  1746.  
  1747. DN_ARROW:
  1748. ;----------------FW----------------------------------------------
  1749.                MOV    BX,DIR_COUNT
  1750.                CMP    BX,21
  1751.                JA     DN_ARROW1
  1752.                MOV    BX,LINE
  1753.                ADD    BX,160
  1754.                CMP    BX,PAGE_END            ;AT LAST LINE
  1755.                JAE    HOME_BAR
  1756.                JMP    DN_ARROW2
  1757.  
  1758. DN_ARROW1:     MOV    BX,CUR_OFFSET
  1759.                ADD    BX,21*DIR_RECORD+160
  1760.                CMP    BX,END_OFFSET          ;AT LAST PAGE
  1761.                JB     DN_ARROW2
  1762.                MOV    BX,LINE
  1763.                ADD    BX,160
  1764.                CMP    BX,PAGE_END            ;AT LAST LINE
  1765.                JAE    HOME_BAR
  1766.                JMP    DN_ARROW2
  1767. ;----------------------------------------------------------------
  1768. DN_ARROW2:     MOV    BP,160                 ;Move bar down one line.
  1769.                CALL   SCROLL_BAR
  1770.                RET
  1771.  
  1772. PG_UP:         MOV    BP,-21*40              ;Move up 21 lines.
  1773.                CALL   SCROLL
  1774.                JMP    SHORT BOTTOM_BAR
  1775.  
  1776. PG_DN:         MOV    BP,21*40               ;Move down 21 lines.
  1777. MOVE_PAGE:     CALL   SCROLL
  1778.                JMP    SHORT TOP_BAR          ;Move bar to top.
  1779.  
  1780. HOME_BAR:      MOV    CUR_OFFSET,OFFSET DIRECTORIES ;Move listing to beginning.
  1781. TOP_BAR:       MOV    SI,PAGE_START                 ;And move bar to top.
  1782.                CALL   MOVE_BAR
  1783.                CALL   SCROLL_TOP             ;FW TOP CHECK
  1784.                RET
  1785.  
  1786. END_BAR:       MOV    BX,END_OFFSET          ;Move listing to last page.
  1787.                SUB    BX,21*DIR_RECORD
  1788.                CMP    BX,OFFSET DIRECTORIES
  1789.                JBE    BOTTOM_BAR
  1790.                MOV    CUR_OFFSET,BX
  1791. BOTTOM_BAR:    MOV    SI,PAGE_END            ;And move bar to bottom.
  1792.                SUB    SI,160
  1793.                CALL   MOVE_BAR
  1794.                CALL   SCROLL_TOP             ;FW TOP CHECK
  1795.                RET
  1796.  
  1797. ;-------------------------------------;
  1798. ; FW MODIFICATION FOR NOT ROOT SHOWING;
  1799. ;-------------------------------------;
  1800. SCROLL_TOP:     PUSH   AX
  1801.                 MOV    AX,CUR_OFFSET            ; WHAT CURRENT OFFSET
  1802.                 CMP    AX,OFFSET DIRECTORIES    ; IS IT THE ROOT?
  1803.                 JNZ    SCROLL_TOP_END           ; NO OUT
  1804.                 MOV    AL,CS:USE_DIRECTORY      ;
  1805.                 CMP    AL,32                   ; IS IT DIR TYPE?
  1806.                 JZ     SCROLL_TOP_END           ; NO DON'T COMPARE
  1807.                 MOV    AX,BAR_START             ; LOAD BAR TOP
  1808.                 CMP    AX,LINE                  ;BAR ON TOP LINE
  1809.                 JNZ    SCROLL_TOP_END           ; NO OUT
  1810.                 MOV    BP,160                   ;Move bar DOWN one line.
  1811.                 CALL   SCROLL_BAR
  1812. SCROLL_TOP_END: POP    AX
  1813.                 RET
  1814.  
  1815. ;----------------------------------------------;
  1816. ; These subroutines support the ten functions. ;
  1817. ;----------------------------------------------;
  1818.  
  1819. CHMOD:         MOV    AX,4301H
  1820.                INT    21H
  1821.                RET
  1822.  
  1823. ;--------------------------------------;
  1824.  
  1825. DELAY:         MOV    AH,1
  1826.                INT    16H                    ;Loop here until keystroke.
  1827.                JZ     DELAY
  1828.                CALL   CLEAR_MSG
  1829.                RET
  1830.  
  1831. ;-------------------------------------;
  1832.  
  1833. DELETE:        MOV    DX,OFFSET DTA_AREA+30   ;Point to filename.
  1834. ;DELETE:        MOV    DX,80H+30              ;Point to filename.
  1835.                MOV    AH,41H
  1836.                INT    21H
  1837.                RET
  1838.  
  1839. ;--------------------------------------;
  1840.  
  1841. DO_ATTRIB:     CALL   FIRST_MATCH            ;Find first file.
  1842. NEXT_SET:      MOV    CL,DS:[80H+21]         ;Get old attribute.
  1843.                AND    CL,STRIP_MASK          ;Strip request.
  1844.                OR     CL,ADD_MASK            ;Add request.
  1845.                XOR    CH,CH                  ;Zero in high half.
  1846.                MOV    DX,80H+30              ;Point to filename.
  1847.                CALL   CHMOD                  ;And change the attribute.
  1848.                CALL   NEXT_MATCHING          ;Do it to all files.
  1849.                JNC    NEXT_SET
  1850.                RET
  1851.  
  1852. ;--------------------------------------;
  1853.  
  1854. FIRST_MATCH:   MOV    DX,OFFSET STAR_DOT_STAR
  1855.                MOV    CX,7
  1856.                MOV    AH,4EH
  1857.                INT    21H
  1858.                RET
  1859.  
  1860. NEXT_MATCHING: MOV    AH,4FH
  1861.                INT    21H
  1862.                RET
  1863. ;------------------------------------------------------;
  1864. ; This subroutine gets a directory name from the user. ;
  1865. ;------------------------------------------------------;
  1866.  
  1867. BRQUERY:
  1868.                PUSH   CX                     ;SAVE CX COUNT
  1869.                PUSH   DI                     ;SAVE DI COUNT
  1870.                CALL   DISPLAY_TEXT           ;Display caller's message.
  1871.                INC    DH                     ;Next row.
  1872.                CALL   SET_CURSOR             ;Move cursor.
  1873.                CALL   CURSOR_ON              ;Turn it on.
  1874.                POP    DI                     ;SAVE DI COUNT
  1875.                POP    CX                     ;SAVE CX COUNT
  1876.                PUSH   CX                     ;SAVE CX COUNT
  1877.                PUSH   DI                     ;SAVE DI COUNT
  1878.                MOV    AX,"  "
  1879.                REP    STOSB
  1880.                POP    DI                     ;SAVE DI COUNT
  1881.                POP    CX                     ;SAVE CX COUNT
  1882.                MOV    BX,CX                  ;POINT TO LAST CHAR
  1883.                ADD    CX,DI                  ;POINT TO LAST CHAR
  1884.                PUSH   DI                     ;SAVE DI COUNT
  1885.  
  1886. BRGET_QUERY:   CALL   READ_KEY               ;Get a character.
  1887.                CMP    AL,27                  ;Is it Esc?
  1888.                JZ     BRQUERY_DONT             ;Is yes, exit subroutine.
  1889. ;              CMP    AL,':'                 ;Ignore ":".
  1890. ;              JZ     BRGET_QUERY
  1891.                CMP    AL,13                  ;Is it carriage return?
  1892.                JZ     BRQUERY_DO               ;If yes, return, do request.
  1893.                CMP    AL,8                   ;Is it backspace?
  1894.                JNZ    BRNOT_BS                 ;If no, skip.
  1895.                CMP    DI,BX                  ;At beginning of field?
  1896.                JZ     BRGET_QUERY              ;If yes, skip.
  1897.                DEC    DI                     ;Else, decrement pointer.
  1898.                MOV    SI,OFFSET BS           ;Erase last character.
  1899.                CALL   GET_TEXT
  1900.                JMP    SHORT BRGET_QUERY
  1901. BRNOT_BS:      CMP    AL,32                  ;Is it above space?
  1902.                JB     BRGET_QUERY              ;If no, ignore.
  1903.                CMP    DI,CX                  ;End of entry field?
  1904.                JZ     BRGET_QUERY              ;If yes, ignore.
  1905.                STOSB                         ;Else, store byte.
  1906.                CALL   WRITE_TEXT             ;And write it to screen.
  1907.                JMP    SHORT BRGET_QUERY        ;Get next keystroke.
  1908.  
  1909. BRQUERY_DO:
  1910.                POP    SI                     ;RESORE DI TO SI
  1911.                CMP    DI,SI                  ;WAS ANOTHING ENTERED
  1912.                JE     BRQUERY_DONT2          ;NO
  1913.                CALL   CURSOR_OFF             ;Turn it OFF
  1914.                CLC
  1915.                RET
  1916.  
  1917. BRQUERY_DONT:  POP   SI
  1918. BRQUERY_DONT2:
  1919.                CALL   CURSOR_OFF             ;Turn it OFF
  1920.                STC                           ;Indicate Esc was pressed.
  1921.                RET
  1922.  
  1923. ;------------------------------------------------------;
  1924. ; This subroutine gets a directory name from the user. ;
  1925. ;------------------------------------------------------;
  1926.  
  1927. QUERY:         CALL   DISPLAY_TEXT           ;Display caller's message.
  1928.                MOV    SI,DIR_NAME            ;Add directory name.
  1929.                CALL   GET_TEXT
  1930.                INC    DH                     ;Next row.
  1931.                CALL   SET_CURSOR             ;Move cursor.
  1932.                CALL   CURSOR_ON              ;Turn it on.
  1933.                MOV    DI,80H                 ;Write nulls over old entry.
  1934.                XOR    AX,AX
  1935.                MOV    CX,18
  1936.                REP    STOSW
  1937.                MOV    DI,80H                 ;Initiate pointer for entry.
  1938.  
  1939. GET_QUERY:     CALL   READ_KEY               ;Get a character.
  1940.                CMP    AL,27                  ;Is it Esc?
  1941.                JZ     QUERY_DONT             ;Is yes, exit subroutine.
  1942.                CMP    AL,':'                 ;Ignore ":\?*".
  1943.                JZ     GET_QUERY
  1944.                CMP    AL,'\'
  1945.                JZ     GET_QUERY
  1946.                CMP    AL,'?'
  1947.                JZ     GET_QUERY
  1948.                CMP    AL,'*'
  1949.                JZ     GET_QUERY
  1950.                CMP    AL,13                  ;Is it carriage return?
  1951.                JZ     QUERY_DO               ;If yes, return, do request.
  1952.                CMP    AL,8                   ;Is it backspace?
  1953.                JNZ    NOT_BS                 ;If no, skip.
  1954.                CMP    DI,80H                 ;At beginning of field?
  1955.                JZ     GET_QUERY              ;If yes, skip.
  1956.                DEC    DI                     ;Else, decrement pointer.
  1957.                MOV    SI,OFFSET BS           ;Erase last character.
  1958.                CALL   GET_TEXT
  1959.                JMP    SHORT GET_QUERY
  1960. NOT_BS:        CMP    AL,32                  ;Is it above space?
  1961.                JBE    GET_QUERY              ;If no, ignore.
  1962.                CMP    DI,8CH                 ;End of entry field?
  1963.                JZ     GET_QUERY              ;If yes, ignore.
  1964.                STOSB                         ;Else, store byte.
  1965.                CALL   WRITE_TEXT             ;And write it to screen.
  1966.                JMP    SHORT GET_QUERY        ;Get next keystroke.
  1967.  
  1968. QUERY_DO:      MOV    BYTE PTR DS:[DI],0     ;Convert to ASCIIZ.
  1969.                CALL   CURSOR_OFF             ;Turn it OFF
  1970.                CLC
  1971.                RET
  1972.  
  1973. QUERY_DONT:
  1974.                CALL   CURSOR_OFF             ;Turn it OFF
  1975.                STC                           ;Indicate Esc was pressed.
  1976.                RET
  1977.  
  1978. ;--------------------------------------------;
  1979. ; This subroutine gets a file count and      ;
  1980. ; displacement of the highlighted directory. ;
  1981. ;--------------------------------------------;
  1982.  
  1983. COUNT_THEM:    MOV    COUNT,0                ;Zero out file counter.
  1984.                MOV    CLUST_COUNT,0          ;And cluster counter.
  1985.                MOV    CLUST_COUNT_1_2MEG,0    ;And cluster counter.
  1986.                MOV    CLUST_COUNT_1_4MEG,0    ;And cluster counter.
  1987.                MOV    CLUST_COUNT_360K,0      ;And cluster counter.
  1988.                MOV    DISKS_1_2MEG,0          ;DISK counter.
  1989.                MOV    DISKS_1_4MEG,0          ;DISK counter.
  1990.                MOV    DISKS_360K,0            ;DISK counter.
  1991.                CALL   FIRST_MATCH            ;Get first file.
  1992.                JC     DISPLAY_COUNT
  1993.  
  1994. FIND_NEXT:     INC    COUNT                  ;Increment file count.
  1995. ;-----------------------FW---------------------------------------------
  1996.                MOV    AX,DS:[DTA_AREA+26]    ;Retrieve low word
  1997.                MOV    DX,DS:[DTA_AREA+28]    ; and high word of file size.
  1998.                ADD    AX,128                 ;128 BYTES ADDED BY BACKUP
  1999.                DIV    CLUST_BYTES_1_2MEG     ;Divide to get cluster count 1.2MEG
  2000.                OR     DX,DX                  ;If remainder, increment count.
  2001.                JZ     NO_REM_1_2MEG
  2002.                INC    CLUST_COUNT_1_2MEG
  2003. NO_REM_1_2MEG: ADD    CLUST_COUNT_1_2MEG,AX   ;Add cluster count.
  2004.  
  2005.                MOV    AX,DS:[DTA_AREA+26]    ;Retrieve low word
  2006.                MOV    DX,DS:[DTA_AREA+28]    ; and high word of file size.
  2007.                ADD    AX,128                 ;128 BYTES ADDED BY BACKUP
  2008.                DIV    CLUST_BYTES_1_4MEG     ;Divide to get cluster count 1.2MEG
  2009.                OR     DX,DX                  ;If remainder, increment count.
  2010.                JZ     NO_REM_1_4MEG
  2011.                INC    CLUST_COUNT_1_4MEG
  2012. NO_REM_1_4MEG: ADD    CLUST_COUNT_1_4MEG,AX   ;Add cluster count.
  2013.  
  2014.                MOV    AX,DS:[DTA_AREA+26]    ;Retrieve low word
  2015.                MOV    DX,DS:[DTA_AREA+28]    ; and high word of file size.
  2016.                ADD    AX,128                 ;128 BYTES ADDED BY BACKUP
  2017.                DIV    CLUST_BYTES_360K    ;Divide to get cluster count 360K
  2018.                OR     DX,DX                  ;If remainder, increment count.
  2019.                JZ     NO_REM_360K
  2020.                INC    CLUST_COUNT_360K
  2021. NO_REM_360K:   ADD    CLUST_COUNT_360K,AX   ;Add cluster count.
  2022.  
  2023. ;----------------------------------------------------------------------
  2024.                MOV    AX,DS:[DTA_AREA+26]    ;Retrieve low word
  2025.                MOV    DX,DS:[DTA_AREA+28]    ; and high word of file size.
  2026.                DIV    CLUST_BYTES            ;Divide to get cluster count.
  2027.                OR     DX,DX                  ;If remainder, increment count.
  2028.                JZ     NO_REMAINDER
  2029.                INC    CLUST_COUNT
  2030. NO_REMAINDER:  ADD    CLUST_COUNT,AX         ;Add cluster count.
  2031.                CALL   NEXT_MATCHING          ;Find rest of files.
  2032.                JNC    FIND_NEXT
  2033.  
  2034. DISPLAY_COUNT: MOV    DX,1629H               ;Row 21; column 41.
  2035.                CALL   SET_CURSOR
  2036.                CALL   GET_COUNT              ;Display count.
  2037.                MOV    SI,OFFSET FILE_COUNT   ;And message.
  2038.                CALL   GET_TEXT
  2039.                MOV    SI,DIR_NAME            ;Display parent directory.
  2040.                CALL   GET_TEXT
  2041.                MOV    SI,OFFSET USING        ;Display rest of message.
  2042.                CALL   GET_TEXT
  2043.                MOV    AX,CLUST_COUNT         ;Retrieve cluster count.
  2044.                XOR    DX,DX                  ;Zero in high half.
  2045.                MOV    BX,CLUST_BYTES
  2046.                MUL    BX                     ;Multiply to get total bytes.
  2047.                MOV    BX,1024
  2048.                DIV    BX                     ;Divide by one K bytes.
  2049.                MOV    COUNT,AX
  2050.                CALL   GET_COUNT              ;Convert count to ASCII.
  2051.                MOV    AL,'K'                 ;Tack on "K".
  2052.                CALL   WRITE_TEXT
  2053. ;-----------------------FW---------------------------------------------
  2054.                XOR    DX,DX                  ;Zero in high half.
  2055.                MOV    AX,CLUST_COUNT_1_2MEG  ;CNT OF 1.2MEG CLUSTERS USED
  2056.                DIV    CLUSTERS_1_2MEG        ;Divide to get NO DISKS
  2057.                OR     DX,DX                  ;If remainder, increment count.
  2058.                JZ     NO_REM_1_2MEG_D
  2059.                INC    DISKS_1_2MEG
  2060. NO_REM_1_2MEG_D: ADD    DISKS_1_2MEG,AX      ;Add DISK count.
  2061.                XOR    DX,DX                  ;Zero in high half.
  2062.                MOV    AX,CLUST_COUNT_1_4MEG  ;CNT OF 1.4MEG CLUSTERS USED
  2063.                DIV    CLUSTERS_1_4MEG        ;Divide to get NO DISKS
  2064.                OR     DX,DX                  ;If remainder, increment count.
  2065.                JZ     NO_REM_1_4MEG_D
  2066.                INC    DISKS_1_4MEG
  2067. NO_REM_1_4MEG_D: ADD    DISKS_1_4MEG,AX      ;Add DISK count.
  2068.                XOR    DX,DX                  ;Zero in high half.
  2069.                MOV    AX,CLUST_COUNT_360K    ;CNT OF 360K CLUSTERS USED
  2070.                DIV    CLUSTERS_360K          ;Divide to get NO DISKS
  2071.                OR     DX,DX                  ;If remainder, increment count.
  2072.                JZ     NO_REM_360K_D
  2073.                INC    DISKS_360K
  2074. NO_REM_360K_D: ADD    DISKS_360K,AX      ;Add DISK count.
  2075.                MOV    AX,COUNT
  2076.                PUSH   AX                     ;SAVE COUNT
  2077.                MOV    DX,1629H               ;Row 22; column 41.
  2078.                CALL   SET_CURSOR
  2079.                MOV    SI,OFFSET BACKUP_USES  ;DISPLAY MESSAGE
  2080.                CALL   GET_TEXT
  2081.                MOV    AX,DISKS_1_2MEG
  2082.                MOV    COUNT,AX               ;1.2MEG COUNT
  2083.                CALL   GET_COUNT              ;Display count.
  2084.                MOV    SI,OFFSET BACKUP_USES_1_2MEG ;DISPLAY MESSAGE
  2085.                CALL   GET_TEXT
  2086.  
  2087.                MOV    DX,1729H               ;Row 23; column 41.
  2088.                CALL   SET_CURSOR
  2089.                MOV    SI,OFFSET BACKUP_USES  ;DISPLAY MESSAGE
  2090.                CALL   GET_TEXT
  2091.                MOV    AX,DISKS_1_4MEG
  2092.                MOV    COUNT,AX               ;360K COUNT
  2093.                CALL   GET_COUNT              ;Display count.
  2094.                MOV    SI,OFFSET BACKUP_USES_1_4MEG ;DISPLAY MESSAGE
  2095.                CALL   GET_TEXT
  2096.  
  2097.                MOV    DX,1829H               ;Row 23; column 41.
  2098.                CALL   SET_CURSOR
  2099.                MOV    SI,OFFSET BACKUP_USES  ;DISPLAY MESSAGE
  2100.                CALL   GET_TEXT
  2101.                MOV    AX,DISKS_360K
  2102.                MOV    COUNT,AX               ;360K COUNT
  2103.                CALL   GET_COUNT              ;Display count.
  2104.                MOV    SI,OFFSET BACKUP_USES_360K  ;DISPLAY MESSAGE
  2105.                CALL   GET_TEXT
  2106.                POP    AX
  2107.                MOV    COUNT,AX               ;SAVE COUNT
  2108. ;----------------------------------------------------------------------
  2109.                RET
  2110.  
  2111. ;------------------------------------------------------;
  2112. ; This subroutine displays the loading message and     ;
  2113. ; reads the disk on reads requested from command line. ;
  2114. ;------------------------------------------------------;
  2115.  
  2116. FIRST_READ:    CALL   CLS
  2117.                MOV    DX,0C18H
  2118.                MOV    SI,OFFSET LOADING
  2119.                CALL   DISPLAY_TEXT
  2120.  
  2121. ;-------------------------------------------------------------------;
  2122. ; This subroutine reads the root directory and FAT from disk.       ;
  2123. ; Then finds subdirectories stacking them in the database one level ;
  2124. ; at a time.  Finally, the database is alphabetized by level.       ;
  2125. ;-------------------------------------------------------------------;
  2126.  
  2127. READ_DATA:     MOV    AX,DISK_BLOCK[2]            ;Retrieve bytes per sector.
  2128.                MOV    BL,BYTE PTR DISK_BLOCK[4]   ;And sectors per cluster -1.
  2129.                INC    BL                          ;Adjust.
  2130.                XOR    BH,BH                  ;Zero high byte.
  2131.                MOV    CLUST_SECTORS,BX       ;And save.
  2132.                MUL    BX                     ;Get total bytes per cluster.
  2133.                MOV    CLUST_BYTES,AX         ;And save.
  2134.                MOV    CX,32                  ;Divide by bytes per directory.
  2135.                DIV    CX
  2136.                MOV    CLUST_RECORDS,AX       ;And save.
  2137.  
  2138. GET_ROOT:      MOV    AX,DISK_BLOCK[9]       ;Retrieve number of root entries.
  2139.                MOV    CX,32                  ;Times 32 byte record length.
  2140.                MUL    CX
  2141.                JNC    NO_ERROR               ;Problem if carry.
  2142. DISK_EXIT:     MOV    DX,OFFSET UNKNOWN      ;Display message and exit.
  2143. ERROR_EXIT:    CALL   RESTORE_DRIVE
  2144. MSG_EXIT:      MOV    AH,9
  2145.                INT    21H
  2146.                CALL   CURSOR_ON
  2147.                INT    20H
  2148.  
  2149. NO_ERROR:      MOV    BX,DISK_BLOCK[2]       ;Divide by bytes per sector.
  2150.                DIV    BX
  2151.                MOV    ROOT_SECTORS,AX        ;That's root length in sectors.
  2152.                MOV    CX,AX                  ;Root length.
  2153.                MOV    DX,DISK_BLOCK[16]         ;Directory starting sector.
  2154.                MOV    BX,OFFSET ROOT_DIRECTORY  ;Read the root directory.
  2155.                CALL   READ_DISK
  2156.  
  2157.                MOV    AX,DATA_SEGMENT           ;Get data storage segment.
  2158.                MOV    ES,AX
  2159.                XOR    BP,BP                     ;Tree level counter.
  2160.                XOR    BX,BX                     ;Entry number counter.
  2161.                MOV    SI,OFFSET ROOT_DIRECTORY  ;Point to root directory.
  2162.                MOV    DI,OFFSET DATA_BUFFER     ;Point to database storage.
  2163.                MOV    BYTE PTR ES:[DI],0FFH     ;Initialize with end signature.
  2164.                MOV    ES:LEVEL_ADDRESS,DI       ;Store starting level address.
  2165.                MOV    CX,DISK_BLOCK[9]          ;Retrieve no. root directories.
  2166.                CALL   STORE_RECORD              ;Store them in database.
  2167.                CMP    BX,0                      ;BX returns with no. entries.
  2168.                JZ     DATA_END                  ;If none, done here.
  2169.  
  2170. GET_FAT:       PUSH   BX                          ;Save entry count.
  2171.                MOV    AL,BYTE PTR DISK_BLOCK[15]  ;Retrieve sectors for FAT.
  2172.                XOR    AH,AH                       ;Zero in high byte.
  2173.                MOV    CX,AX                     ;Save.
  2174.                MOV    BX,DISK_BLOCK[2]          ;Retrieve byte per sector.
  2175.                MUL    BX                        ;Multiply to get total bytes.
  2176.                JC     DISK_EXIT                 ;Problem if carry.
  2177.                CMP    AX,65535-8192             ;Too big if over 56K.
  2178.                JA     DISK_EXIT                 ;Display message and exit.
  2179.                MOV    DX,DISK_BLOCK[6]          ;Retrieve reserved sectors.
  2180.                MOV    BX,OFFSET FAT             ;Read the FAT.
  2181.                CALL   READ_DISK
  2182.                JC     ERROR_EXIT                ;Exit if problem.
  2183.  
  2184.                POP    BX                        ;Retrieve directory count.
  2185.                MOV    AX,DATA_SEGMENT           ;Point to database segment.
  2186.                MOV    ES,AX
  2187.                MOV    SI,OFFSET DATA_BUFFER     ;And point to database offset.
  2188. UP_LEVEL:      INC    BP                        ;Bump point to next level.
  2189.                INC    BP
  2190.                MOV    ES:[OFFSET LEVEL_ADDRESS+BP],DI   ;Save level address.
  2191.                MOV    CX,BX                             ;Retrieve record count.
  2192.                XOR    BX,BX                  ;Zero out entry counter.
  2193. NEXT_SECTOR:   MOV    DX,ES:[SI+16]          ;Retrieve starting cluster.
  2194.  
  2195. NEXT_CLUSTER:  MOV    LAST_CLUSTER,DX        ;And save.
  2196.                PUSH   CX                     ;Save some registers.
  2197.                PUSH   BX
  2198.                CALL   READ_CLUSTER           ;Retrieve directory sector.
  2199.                POP    BX
  2200.                MOV    DX,ES:[SI+1]           ;Retrieve parent entry number.
  2201.                PUSH   SI
  2202.                MOV    SI,OFFSET WORKSPACE    ;Point to new directory.
  2203.                MOV    CX,CLUST_RECORDS       ;Retrieve records per cluster.
  2204.                CALL   STORE_RECORD           ;Store subdirectories in database.
  2205.                POP    SI
  2206.                POP    CX
  2207.                JC     END_LEVEL              ;If carry, last entry found.
  2208.                CALL   CK_FAT                 ;Else, get next cluster.
  2209.                JNC    NEXT_CLUSTER           ;If carry, last cluster found.
  2210.  
  2211. END_LEVEL:     ADD    SI,DATA_RECORD         ;Else, point to next root entry.
  2212.                LOOP   NEXT_SECTOR            ;Find next subdirectory.
  2213.                CMP    SI,DI                  ;Did we find any at this level?
  2214.                JNZ    UP_LEVEL               ;If yes, continue.
  2215.                MOV    AX,0FFFFH              ;Else, done; mark with signature.
  2216.                STOSB
  2217.                MOV    ES:[OFFSET LEVEL_ADDRESS+BP+2],AX   ;Mark level address.
  2218.                CALL   SORT                                ;Alphabetize by level.
  2219. DATA_END:      PUSH   CS                     ;Restore segment registers.
  2220.                PUSH   CS
  2221.                POP    DS
  2222.                POP    ES
  2223.                RET
  2224.  
  2225. ;-------------------------------------------------;
  2226. ; This subroutine does the direct sector reading. ;
  2227. ;-------------------------------------------------;
  2228.  
  2229. READ_DISK:     PUSH   BP                     ;Call destroys all registers
  2230.                PUSH   SI                     ; except segment registers
  2231.                PUSH   DI                     ; so we have to preserve.
  2232.                PUSH   DS
  2233.  
  2234.                MOV    AL,DRIVE               ;Retrieve drive.
  2235.                MOV    SI,DS                  ;Point to second segment.
  2236.                ADD    SI,1000H
  2237.                MOV    DS,SI
  2238.                INT    25H                    ;Read the sectors.
  2239.                POP    AX                     ;Get rid off flags left on stack.
  2240.  
  2241.                POP    DS                     ;Restore registers.
  2242.                POP    DI
  2243.                POP    SI
  2244.                POP    BP
  2245.                RET
  2246.  
  2247. ;----------------------------------------;
  2248. ; This subroutine will read CX clusters. ;
  2249. ;----------------------------------------;
  2250.  
  2251. READ_CLUSTER:  MOV    AX,LAST_CLUSTER        ;Retrieve cluster number.
  2252.                MOV    CX,CLUST_SECTORS       ;Retrieve sectors per cluster.
  2253.                MUL    CX                     ;Multiply to get sector start.
  2254.                MOV    DX,AX
  2255.                ADD    DX,DISK_BLOCK[11]      ;Add start of first data cluster.
  2256.                SUB    DX,CX                  ;Subtract to reflect cluster
  2257.                SUB    DX,CX                  ; 2 as first logical data sector.
  2258.                MOV    BX,OFFSET WORKSPACE    ;Point to workspace.
  2259.                CALL   READ_DISK              ;And get data.
  2260.                RET
  2261.  
  2262. ;------------------------------------------------------------------;
  2263. ; This subroutine stores the level number, entry number, parent    ;
  2264. ; entry number, the directory name and attribute byte in database. ;
  2265. ;------------------------------------------------------------------;
  2266.  
  2267. STORE_RECORD:  PUSH   DS                     ;Point to second segment.
  2268.                MOV    AX,CS
  2269.                ADD    AX,1000H
  2270.                MOV    DS,AX
  2271.  
  2272. NEXT_RECORD:   CMP    BYTE PTR [SI],0        ;No more entries?
  2273.                JZ     STORE_RETURN           ;If yes, done here.
  2274.                TEST   BYTE PTR [SI+11],10H   ;Is it a directory?
  2275.                JZ     LOOP_STORE             ;If no, next entry.
  2276.                CMP    BYTE PTR [SI],0E5H     ;Is it a removed directory?
  2277.                JZ     LOOP_STORE             ;If yes, skip.
  2278.                CMP    BYTE PTR [SI],'.'      ;Is it a dot or dot-dot entry?
  2279.                JZ     LOOP_STORE             ;If yes, skip.
  2280. ;---------------------------------------------------------------------
  2281. ;       FW MOD CHECK FOR ONLY THE DIRECTORY IN PARM
  2282. ;---------------------------------------------------------------------
  2283.                MOV    AL,CS:USE_DIRECTORY       ; 1ST CHAR
  2284.                CMP    AL,32                  ; IS DIR BLANK?
  2285.                JZ     NOT_ROOT               ; YES DON'T COMPARE
  2286.                CMP    BP,0                   ; IS IT THE ROOT?
  2287.                JNZ    NOT_ROOT               ; NO DON'T COMPARE
  2288.                PUSH   CX
  2289.                PUSH   SI
  2290.                PUSH   DI
  2291.                MOV    DI,OFFSET USE_DIRECTORY
  2292.  
  2293.                MOV    CX,11                 ; COUNT FOR COMPARE
  2294.                REPE   CMPSB
  2295.                POP    DI
  2296.                POP    SI
  2297.                POP    CX
  2298.                JNZ    LOOP_STORE            ; NOT EQUAL BYPASS
  2299. ;---------------------------------------------------------------------
  2300. NOT_ROOT:      PUSH   SI
  2301.                MOV    AX,BP                  ;Store level number.
  2302.                STOSB
  2303.                MOV    AX,BX                  ;Store entry number.
  2304.                STOSW
  2305.                MOV    AX,DX                  ;Store parent entry number.
  2306.                STOSW
  2307.                PUSH   CX
  2308.                MOV    CX,11                  ;Store 11 bytes of name.
  2309.                REP    MOVSB
  2310.                POP    CX
  2311.                ADD    SI,15                  ;Store starting cluster.
  2312.                MOVSW
  2313.                INC    BX                     ;Increment entry count.
  2314.                POP    SI
  2315.                XOR    AX,AX                  ;Assume not a hidden directory.
  2316.                TEST   BYTE PTR [SI+11],2     ;Is it hidden?
  2317.                JZ     STORE_ATTRIB           ;If no, store null.
  2318.                MOV    AX,'H'                 ;Else, store "H".
  2319. STORE_ATTRIB:  STOSW
  2320.  
  2321. LOOP_STORE:    ADD    SI,32                  ;Point to next entry.
  2322.                LOOP   NEXT_RECORD
  2323.                POP    DS                     ;Restore segment.
  2324.                CLC                           ;Indicate full sector.
  2325.                RET
  2326.  
  2327. STORE_RETURN:  POP    DS                     ;Indicate not full sector.
  2328.                STC
  2329.                RET
  2330.  
  2331. ;-------------------------------------------------------------------;
  2332. ; This subroutine finds the next cluster in the chain from the FAT. ;
  2333. ;-------------------------------------------------------------------;
  2334.  
  2335. CK_FAT:        PUSH   ES                     ;Save some registers.
  2336.                PUSH   BX
  2337.                PUSH   CX
  2338.                MOV    AX,CS                  ;Point to second segment.
  2339.                ADD    AX,1000H
  2340.                MOV    ES,AX
  2341.  
  2342.                MOV    AX,LAST_CLUSTER        ;Retrieve last cluster.
  2343.                PUSH   AX                     ;Save.
  2344.                XOR    DX,DX                  ;Zero in high half.
  2345.                MOV    BX,DISK_BLOCK[13]
  2346.                CMP    BX,0FF6H    ;Number of clusters above 4085?
  2347.                JA     SIXTEEN_BIT            ;If yes, 16 bit FAT.
  2348. TWELVE_BIT:    MOV    BX,15                  ;Else, 12 bit FAT.
  2349.                MUL    BX                     ;Multiply by 1.5 (or 15/10).
  2350.                MOV    BX,10
  2351.                DIV    BX
  2352.                MOV    BX,AX
  2353.                MOV    DX,ES:FAT[BX]          ;Retrieve cluster pointer.
  2354.                POP    AX                     ;Retrieve last cluster.
  2355.                TEST   AX,1                   ;Was last cluster even number?
  2356.                JZ     LOW_ORDER              ;If yes, use low order 12 bits.
  2357.                MOV    CL,4                   ;Else, high order 12 bits.
  2358.                SHR    DX,CL                  ;Shift right 4 bits.
  2359.                JMP    SHORT CK_12BIT
  2360. LOW_ORDER:     AND    DX,0000111111111111xB   ;Mask off top 4 bits.
  2361. CK_12BIT:      CMP    DX,0FF8H               ;Is it end of chain?
  2362.                JAE    CLUSTER_END            ;If yes, indicate so.
  2363.                JMP    SHORT RETURN_CLUST     ;Else, return with cluster in DX.
  2364.  
  2365. SIXTEEN_BIT:   POP    BX                     ;Retrieve last cluster.
  2366.                SHL    BX,1                   ;Multiply by 2.
  2367.                MOV    DX,ES:FAT[BX]          ;Retrieve next cluster number.
  2368.                CMP    DX,0FFF8H              ;Is it end of chain?
  2369.                JAE    CLUSTER_END            ;If yes, indicate so.
  2370.  
  2371. RETURN_CLUST:  POP    CX                     ;Restore registers.
  2372.                POP    BX
  2373.                POP    ES
  2374.                CLC                           ;Indicate not end of chain.
  2375.                RET
  2376.  
  2377. CLUSTER_END:   POP    CX
  2378.                POP    BX
  2379.                POP    ES
  2380.                STC                           ;Indicate end of cluster chain.
  2381.                RET
  2382.  
  2383. ;--------------------------------------------------------;
  2384. ; This subroutine alphabetizes the directories by level. ;
  2385. ;--------------------------------------------------------;
  2386.  
  2387. SORT:          PUSH   DS
  2388.                MOV    AX,DATA_SEGMENT        ;Point to database segment.
  2389.                MOV    ES,AX
  2390.                MOV    DS,AX
  2391.                XOR    BP,BP                              ;Zero in level pointer.
  2392. LEVEL_SORT:    MOV    DX,ES:[OFFSET LEVEL_ADDRESS+BP+2]  ;Retreive level offset.
  2393.                CMP    DX,0FFFFH                          ;End signature?
  2394.                JZ     SORT_RETURN            ;If yes, done here.
  2395.                SUB    DX,DATA_RECORD         ;Point to end of lower level.
  2396.                PUSH   BP                     ;Save level pointer.
  2397.  
  2398. NEXT_PASS:     POP    BP
  2399.                PUSH   BP
  2400.                MOV    BX,ES:[OFFSET LEVEL_ADDRESS+BP] ;Point to start of level.
  2401.                XOR    BP,BP                           ;Zero in exchange flag.
  2402.                CMP    BX,DX                  ;End of level?
  2403.                JZ     SORT_SET               ;If yes, next level.
  2404.  
  2405. NEXT_SORT:     MOV    SI,BX                  ;Source and destination.
  2406.                ADD    SI,5                   ;Point to name
  2407.                MOV    DI,BX                  ; in each record.
  2408.                ADD    DI,DATA_RECORD+5
  2409.                MOV    CX,11
  2410.                REPZ   CMPSB                  ;Compare names.
  2411.                JBE    END_SORT               ;If already in order, skip.
  2412.  
  2413.                MOV    SI,BX                  ;Else, recover pointers.
  2414.                MOV    DI,BX
  2415.                ADD    DI,DATA_RECORD
  2416.                MOV    CX,DATA_RECORD/2       ;Exchange the records.
  2417. NEXT_SWAP:     MOV    AX,[DI]
  2418.                MOVSW
  2419.                MOV    [SI-2],AX
  2420.                LOOP   NEXT_SWAP
  2421.                MOV    BP,1                   ;Flag that exchange was made.
  2422.  
  2423. END_SORT:      ADD    BX,DATA_RECORD         ;Point to next record.
  2424.                CMP    BX,DX                  ;End of top?
  2425.                JB     NEXT_SORT              ;If no, bubble sort next.
  2426.                SUB    DX,DATA_RECORD         ;Else, move top down one record.
  2427.                CMP    BP,0                   ;Was there exchange made?
  2428.                JNZ    NEXT_PASS
  2429.  
  2430. SORT_SET:      POP    BP
  2431.                INC    BP                     ;Next level.
  2432.                INC    BP
  2433.                JMP    SHORT LEVEL_SORT       ;Sort it.
  2434.  
  2435. SORT_RETURN:   POP    DS                     ;Restore data segment.
  2436.                RET
  2437.  
  2438. ;-------------------------------------------------------------;
  2439. ; This subroutine formats the database into a directory tree. ;
  2440. ;-------------------------------------------------------------;
  2441.  
  2442. FORMAT_IT:     PUSH   DATA_SEGMENT           ;Point to database segment.
  2443.                POP    DS
  2444.                MOV    AX,CS                  ;Point to second segment.
  2445.                ADD    AX,1000H
  2446.                MOV    ES,AX
  2447.                MOV    SI,OFFSET LEVEL_ADDRESS     ;Move resident database
  2448.                MOV    DI,SI                       ; into our second segment.
  2449.                MOV    CX,100+(DATA_RECORD*500/2)
  2450.                REP    MOVSW
  2451.  
  2452.                PUSH   CS                     ;Restore segment registers.
  2453.                PUSH   CS
  2454.                POP    DS
  2455.                POP    ES
  2456.                CALL   STORE_ROOT             ;Initialize with "\ (ROOT)".
  2457.  
  2458.                XOR    BP,BP                              ;Zero in level pointer.
  2459.                MOV    SI,OFFSET DATA_BUFFER              ;Point to database.
  2460.                MOV    DI,OFFSET DIRECTORIES+DIR_RECORD+1 ;Point to storage.
  2461.                MOV    LAST_ENTRY,DI                      ;Save current entry.
  2462.                MOV    AX,CS                  ;Point to second segment.
  2463.                ADD    AX,1000H
  2464.                MOV    DS,AX
  2465.                CMP    BYTE PTR [SI],0FFH     ;No subs signature?
  2466.                JZ     SKIP_FORMAT            ;If yes, skip format.
  2467.  
  2468. NEXT_FORMAT:   CALL   STORE_NAME             ;Format the directory name.
  2469.                ADD    SI,DATA_RECORD         ;Point to next record.
  2470.                CMP    BYTE PTR [SI],0        ;End of root directory?
  2471.                JZ     NEXT_FORMAT            ;If no, get next entry.
  2472. SKIP_FORMAT:   PUSH   CS                     ;Else, done.
  2473.                POP    DS                     ;Restore data segment.
  2474.                DEC    DI                     ;Adjust end pointer.
  2475.                MOV    END_OFFSET,DI          ;And save.
  2476.                MOV    BX,DIR_COUNT           ;Retrieve directory count.
  2477.                CMP    BX,21                  ;Enough to fill one page?
  2478.                JAE    FORMAT_END             ;If yes, use default setting.
  2479.                MOV    AX,160                 ;Calculate last record.
  2480.                MUL    BL
  2481.                ADD    AX,PAGE_START          ;Add bar offset.
  2482.                MOV    PAGE_END,AX            ;And save.
  2483. FORMAT_END:    RET
  2484.  
  2485. ;------------------------------------------------------;
  2486. ; This subroutine initializes the directory tree image ;
  2487. ; with nulls and makes the first record "\ (ROOT)".    ;
  2488. ;------------------------------------------------------;
  2489.  
  2490. STORE_ROOT:    MOV    AX,0
  2491.                MOV    DI,OFFSET DIRECTORIES
  2492.                MOV    CX,30000 / 2
  2493.                REP    STOSW
  2494.  
  2495.                MOV    DI,OFFSET DIRECTORIES
  2496.                MOV    SI,OFFSET ROOT
  2497.                MOV    CX,8
  2498.                REP    MOVSB
  2499.                RET
  2500.  
  2501. ;-----------------------------------------------------------;
  2502. ; This subroutine recursively builds the subdirectory tree. ;
  2503. ;-----------------------------------------------------------;
  2504.  
  2505. STORE_NAME:    PUSH   SI                     ;Save a couple registers.
  2506.                PUSH   BP
  2507.  
  2508.                PUSH   DI                     ;Save pointers.
  2509.                PUSH   SI
  2510.                PUSH   SI
  2511.                MOV    SI,CS:LAST_ENTRY       ;Retrieve last entry.
  2512.                MOV    DX,DI                  ;Retrieve current position.
  2513.                CMP    SI,DX                  ;Have stored any subdirectories?
  2514.                JZ     STORE_DIR                ;If no, skip tree structuring.
  2515.                MOV    BYTE PTR CS:[SI+BP],195  ;Store connecting T character.
  2516. PLACE_BAR:     ADD    SI,DIR_RECORD            ;Move to next record.
  2517.                CMP    SI,DX                    ;Are we at the current record?
  2518.                JZ     STORE_DIR                ;If yes, done here.
  2519.                MOV    BYTE PTR CS:[SI+BP],179  ;Else, store vertical line char.
  2520.                JMP    SHORT PLACE_BAR          ;Repeat until up to date.
  2521.  
  2522. STORE_DIR:     MOV    CS:LAST_ENTRY,SI       ;Store current position.
  2523.                POP    SI                     ;Restore current record pointer.
  2524.                INC    CS:DIR_COUNT           ;Increment directory counter.
  2525.                ADD    DI,BP                  ;Add level pointer.
  2526.                MOV    AL,192                 ;Store L line character.
  2527.                STOSB
  2528.                MOV    AL,196                 ;Store horizontal line character.
  2529.                STOSB
  2530.                ADD    SI,5                   ;Point to directory name.
  2531.                MOV    CX,8
  2532.                CALL   STORE_BYTES            ;And store in tree.
  2533.                CMP    BYTE PTR [SI],32
  2534.                JZ     END_NAME
  2535.                MOV    AL,'.'                 ;If exists, append extension.
  2536.                STOSB
  2537.                MOV    CX,3
  2538.                CALL   STORE_BYTES
  2539. END_NAME:      POP    SI                     ;Restore current record pointer.
  2540.                INC    DI                     ;Bump pointer for space.
  2541.                MOV    AL,[SI+18]             ;Retrieve "hidden" field.
  2542.                STOSB                         ;And store it.
  2543. NEXT_DEST:     POP    DI                     ;Restore destination pointer.
  2544.                ADD    DI,DIR_RECORD          ;Point to next tree record.
  2545.  
  2546.                PUSH   CS:LAST_ENTRY          ;Save current position pointer.
  2547.                MOV    CS:LAST_ENTRY,DI       ;Save our current position.
  2548.                INC    BP                     ;Bump pointer to next level.
  2549.                INC    BP
  2550.                MOV    BX,DS:[OFFSET LEVEL_ADDRESS+BP] ;Get level offset.
  2551.  
  2552. NEXT_SUB:      MOV    AL,DS:[BX]             ;Retrieve level pointer.
  2553.                XOR    AH,AH
  2554.                CMP    AX,BP                  ;Is it our level?
  2555.                JA     STORE_END              ;If next level, done here.
  2556.                MOV    AX,DS:[BX+3]           ;Retrieve parent entry number.
  2557.                CMP    AX,DS:[SI+1]           ;Is it our entry number?
  2558.                JNZ    SKIP_SUB               ;If no, check next record.
  2559.  
  2560. GET_SUB:       PUSH   BX                     ;Else, save pointers.
  2561.                PUSH   SI
  2562.                MOV    SI,BX                  ;Point to our offset.
  2563.                CALL   STORE_NAME             ;Store subdirectory.
  2564.                POP    SI                     ;Restore pointers.
  2565.                POP    BX
  2566.  
  2567. SKIP_SUB:      ADD    BX,DATA_RECORD         ;Next record.
  2568.                JMP    SHORT NEXT_SUB
  2569.  
  2570. STORE_END:     POP    CS:LAST_ENTRY          ;Restore last entry pointer.
  2571.                POP    BP
  2572.                POP    SI
  2573.                RET
  2574.  
  2575. ;--------------------------------------;
  2576.  
  2577. STORE_BYTES:   LODSB                         ;Store all non space name
  2578.                CMP    AL,32                  ; characters.
  2579.                JZ     SKIP_STORE
  2580.                STOSB
  2581. SKIP_STORE:    LOOP   STORE_BYTES
  2582.                RET
  2583.  
  2584. ;-----------------------------------------------------------------;
  2585. ; This subdirectory works its way back to the root directory from ;
  2586. ; the currently highlighted directory and then retraces back up   ;
  2587. ; the tree changing the default directory one level at a time.    ;
  2588. ;-----------------------------------------------------------------;
  2589.  
  2590. NEW_DIR:       MOV    COUNT,0                ;Zero out path counter.
  2591.                MOV    DX,OFFSET ROOT_DIR     ;Change to root directory.
  2592.                CALL   CD
  2593.                XOR    CX,CX                  ;Zero in level counter.
  2594.                MOV    DI,CUR_RECORD          ;Point to highlighted record.
  2595.                CMP    DI,OFFSET DIRECTORIES  ;Is it the root?
  2596.                JZ     NEW_DIR_END            ;If yes, done here.
  2597.                MOV    BX,DIR_NAME            ;Point to directory name.
  2598.                DEC    BX                     ;Point to horizontal character.
  2599.  
  2600. NEXT_SUBDIR:   MOV    SI,BX
  2601. FIND_DIR:      LODSB                         ;Get a byte.
  2602.                CMP    AL,196                 ;Is it horizonatal character?
  2603.                JNZ    FIND_DIR               ;If no, find it.
  2604.                PUSH   SI                     ;Save directory.
  2605.                INC    CX                     ;Also keep track of level.
  2606. NEXT_PATH:     INC    COUNT                  ;Increment path length.
  2607.                LODSB
  2608.                CMP    AL,0                   ;Are we at end of directory name?
  2609.                JNZ    NEXT_PATH              ;If no, find it.
  2610.                CMP    BYTE PTR [DI+2],196    ;Is there a level under us?
  2611.                JZ     CHANGE_THEM            ;If no, done here.
  2612.                DEC    BX                     ;Else, decrement level pointer.
  2613.                DEC    BX
  2614. NEXT_LEVEL:    SUB    DI,DIR_RECORD          ;Look for next lower level.
  2615.                SUB    BX,DIR_RECORD
  2616.                CMP    BYTE PTR [BX],196      ;Have we found parent record?
  2617.                JNZ    NEXT_LEVEL             ;If no, find it.
  2618.                JMP    SHORT NEXT_SUBDIR      ;And find name and length.
  2619.  
  2620. CHANGE_THEM:   POP    DX                     ;Retrieve directory name pointer.
  2621.                CALL   CD                     ;Change directories.
  2622.                JC     RESTORE_STACK          ;If nonexistant, restore stack
  2623.                LOOP   CHANGE_THEM            ;Else, continue up the tree.
  2624. NEW_DIR_END:   RET
  2625.  
  2626. NEXT_STACK:    POP    DX                     ;If error, restore stack
  2627.                CALL   BEEP                   ;Change directories.
  2628.                CALL   BEEP                   ;Change directories.
  2629.                CALL   BEEP                   ;Change directories.
  2630. RESTORE_STACK: LOOP   NEXT_STACK             ; before returning.
  2631.                RET
  2632.  
  2633. ;--------------------------------------;
  2634.  
  2635. CD:            MOV    AH,3BH
  2636.                INT    21H
  2637.                RET
  2638.  
  2639. ;--------------------------------------------------;
  2640. ; This subroutine finds the highlighted directory. ;
  2641. ;--------------------------------------------------;
  2642.  
  2643. GET_NAME:      MOV    SI,CUR_OFFSET          ;Get top of page.
  2644.                MOV    AX,LINE                ;Get location of bar.
  2645.                SUB    AX,PAGE_START          ;Adjust.
  2646.                MOV    CL,160                 ;80 characters + 80 attributes.
  2647.                DIV    CL                     ;Divide to get line number.
  2648.                MOV    CL,DIR_RECORD          ;Times directory record length.
  2649.                MUL    CL
  2650.                ADD    SI,AX                  ;Add to current offset.
  2651.                MOV    CUR_RECORD,SI                    ;And save pointer.
  2652.                CMP    CUR_RECORD,OFFSET DIRECTORIES    ;Is it top line?
  2653.                JZ     NAME_RETURN                      ;If yes, done here.
  2654. FIND_TOP:      LODSB
  2655.                CMP    AL,196                 ;Is it the horizontal line char?
  2656.                JNZ    FIND_TOP               ;If no, find it.
  2657. NAME_RETURN:   MOV    DIR_NAME,SI            ;And store name pointer.
  2658.                MOV    AX,SI
  2659.                SUB    AX,CUR_RECORD          ;CALC LEVEL OF DIR
  2660.                MOV    CUR_LEVEL,AX           ;AND SAVE
  2661.                RET
  2662.  
  2663. ;----------------------------------------------------------;
  2664. ; This subdirectory searches through the graphic tree for  ;
  2665. ; the name of the DOS default directory and highlights it. ;
  2666. ;----------------------------------------------------------;
  2667.  
  2668. GET_CURRENT:   MOV    SI,OFFSET CURRENT_DIR  ;Point to default directory.
  2669.                MOV    BYTE PTR [SI],'\'      ;DOS fails to include starting "\".
  2670.                INC    SI                     ;Point to first level.
  2671.                MOV    DL,DRIVE               ;Retrieve drive.
  2672.                INC    DL                     ;Convert to DOS format.
  2673.                MOV    AH,47H                 ;Retrieve current directory.
  2674.                INT    21H
  2675.                CALL   CAPITALIZE             ;Capitalize it.
  2676.  
  2677.                MOV    BX,OFFSET CURRENT_DIR+1     ;Point to default directory.
  2678.                CMP    BYTE PTR [BX],0             ;Are we at end?
  2679.                JZ     CURRENT_END                           ;If yes, done here.
  2680.                MOV    BP,OFFSET DIRECTORIES+DIR_RECORD+3    ;Store pointer.
  2681.                XOR    DX,DX                                 ;Zero entry counter.
  2682.                MOV    CX,500                 ;Search a maximum of 500 records.
  2683.  
  2684. NEXT_DEFAULT:  INC    DX                     ;Increment entry counter.
  2685.                MOV    SI,BX                  ;Point to default directory.
  2686.                MOV    DI,BP                  ;Point to directory tree.
  2687.                CMP    BYTE PTR [DI-1],196    ;Is it horizontal bar?
  2688.                JNZ    NO_MATCH               ;If no, next record.
  2689. NEXT_MATCH:    CMP    BYTE PTR [DI],0        ;Is it end of tree name?
  2690.                JNZ    CK_DEFAULT             ;If no, see if name matches.
  2691.                CMP    BYTE PTR [SI],'\'      ;Is it end of default level?
  2692.                JZ     MATCH                  ;If yes, then we have a match.
  2693.                CMP    BYTE PTR [SI],0        ;Zero also marks name end.
  2694.                JZ     MATCH
  2695. CK_DEFAULT:    CMPSB                         ;Character in name match?
  2696.                JZ     NEXT_MATCH             ;If yes, check next byte.
  2697. NO_MATCH:      ADD    BP,DIR_RECORD          ;Else, next record.
  2698.                LOOP   NEXT_DEFAULT           ;Search up to 500 records.
  2699.                JMP    SHORT CURRENT_END      ;Give up if not found.
  2700.  
  2701. MATCH:         DEC    CX                     ;Decrement search counter.
  2702.                JZ     CURRENT_END            ;Exit, if not found.
  2703.                INC    SI                     ;Point to name.
  2704.                MOV    BX,SI                  ;Store current level.
  2705.                ADD    BP,DIR_RECORD+2        ;Point to next record and level.
  2706.                CMP    BYTE PTR [SI-1],0      ;End of default?
  2707.                JNZ    NEXT_DEFAULT           ;If no, continue.
  2708.  
  2709. FIND_DEFAULT:  MOV    CX,DIR_COUNT           ;Retrieve directory count.
  2710.                SUB    CX,DX                  ;Subtract default entry counter.
  2711.                MOV    SEARCH_COUNT,CX        ;Save.
  2712.                MOV    CL,ATTR_TREE           ;Turn off bar for now.
  2713.                MOV    BAR_ATTRIBUTE,CL
  2714.                CALL   END_BAR                ;First move to end.
  2715.                JMP    SHORT FIND_IT
  2716. NEXT_FIND:     CALL   UP_ARROW2              ;Move up to matching directory.
  2717. FIND_IT:       DEC    SEARCH_COUNT
  2718.                JNZ    NEXT_FIND
  2719.                MOV    CL,INVERSE             ;Turn bar back on.
  2720.                MOV    BAR_ATTRIBUTE,CL
  2721. CURRENT_END:   RET
  2722.  
  2723. ;-----------------------------------------------------;
  2724. ; This subroutine displays the menu, requested drive, ;
  2725. ; and directory count.  Also displays highlight bar.  ;
  2726. ;-----------------------------------------------------;
  2727.  
  2728. START_DISPLAY:
  2729.                MOV    SI,OFFSET MENU         ;Point to menu position.
  2730.                CMP    DEFAULT_MENU,1
  2731.                JE     LONG_MENU
  2732.                MOV    SI,OFFSET MENU2        ;Point to menu2 position.
  2733. LONG_MENU:     MOV    DI,(1*160)+98          ;And to screen position.
  2734.                MOV    BH,MENU_LGTH           ;Display 19 lines of menu.
  2735. NEXT_FUNCTION:
  2736.                MOV    CX,MENU_WIDTH          ;22 characters per line.
  2737. NEXT_MENU:
  2738.  
  2739.                LODSB
  2740.                MOV    BL,AL
  2741.                CALL   WRITE_SCREEN
  2742. ;----------------------FW--------------------------------------
  2743.                MOV    BL,ATTR_MENU          ;<<<<<<
  2744.                DEC    DI
  2745.                CALL   WRITE_SCREEN
  2746.                DEC    DI
  2747. ;----------------------FW--------------------------------------
  2748.                LOOP   NEXT_MENU
  2749.  
  2750.                MOV    BL,ATTR_TREE           ;<<<<<<
  2751.  
  2752.                ADD    DI,160-(MENU_WIDTH*2)  ;Next line.
  2753.                DEC    BH
  2754.                JNZ    NEXT_FUNCTION
  2755.  
  2756.                MOV    SI,OFFSET HEADING      ;Display "Directories of drive".
  2757.                MOV    DX,1
  2758.                CALL   DISPLAY_TEXT
  2759.                MOV    AL,DRIVE
  2760.                ADD    AL,'A'                 ;Display drive.
  2761.                CALL   WRITE_TEXT
  2762.                MOV    AL,':'                 ;And colon.
  2763.                CALL   WRITE_TEXT
  2764.                CALL   COUNT_DIRS             ;Display directory count.
  2765.                MOV    SI,LINE
  2766.                CALL   MOVE_BAR               ;Highlight the current directory.
  2767. ;--------------FW CHANGE---------------------------------------------
  2768.                CALL   SCROLL_TOP             ;DON'T POINT AT ROOT
  2769. ;--------------------------------------------------------------------
  2770.                RET
  2771.  
  2772. ;----------------------------------------------------;
  2773. ; This subroutine capitalizes the default directory. ;
  2774. ;----------------------------------------------------;
  2775.  
  2776. CAPITALIZE:    CMP    BYTE PTR [SI],'a'
  2777.                JB     NEXT_CAPS
  2778.                CMP    BYTE PTR [SI],'z'
  2779.                JA     NEXT_CAPS
  2780.                AND    BYTE PTR [SI],5FH
  2781. NEXT_CAPS:     INC    SI
  2782.                CMP    BYTE PTR [SI],0
  2783.                JNZ    CAPITALIZE
  2784.                RET
  2785.  
  2786. ;-------------------------------------;
  2787. ; This subroutine scrolls the screen. ;
  2788. ;-------------------------------------;
  2789.  
  2790. SCROLL:        MOV    SI,CUR_OFFSET          ;Get current offset.
  2791.                ADD    SI,BP                  ;Add requested direction.
  2792. CK_LOWER:      CMP    SI,OFFSET DIRECTORIES  ;If above start check uppe limit.
  2793.                JAE    UPPER_LIMIT
  2794. LOWER_LIMIT:   MOV    CUR_OFFSET,OFFSET DIRECTORIES   ;Else, make it start.
  2795.                JMP    SHORT SCROLL_RETURN             ;And update screen.
  2796.  
  2797. UPPER_LIMIT:   MOV    BX,END_OFFSET                        ;See if beyond end of
  2798.                CMP    BX,OFFSET DIRECTORIES+21*DIR_RECORD  ; directory listing.
  2799.                JA     CK_UPPER
  2800.                MOV    CUR_OFFSET,OFFSET DIRECTORIES
  2801.                MOV    AT_LAST_LINE,"="        ;SAY AT LAST LINE
  2802.                JMP    SHORT SCROLL_RETURN
  2803.  
  2804. CK_UPPER:      SUB    BX,21*DIR_RECORD
  2805.                CMP    SI,BX
  2806.                JBE    END_SCROLL
  2807.                MOV    AT_LAST_LINE,"="        ;SAY AT LAST LINE
  2808.                MOV    SI,BX
  2809.  
  2810. END_SCROLL:    MOV    CUR_OFFSET,SI          ;Update current offset.
  2811.                MOV    SI,LINE
  2812.                CALL   MOVE_BAR
  2813. SCROLL_RETURN: RET
  2814.  
  2815. ;--------------------------------------------------;
  2816. ; This subroutine scrolls the bar if between start ;
  2817. ; and end of page. Otherwise the page is scrolled. ;
  2818. ;--------------------------------------------------;
  2819.  
  2820. SCROLL_BAR:    MOV    SI,LINE                ;Get current line.
  2821.                ADD    SI,BP                  ;Add requested line.
  2822.                MOV    BP,-DIR_RECORD         ;Assume below beginning.
  2823.                CMP    SI,PAGE_START          ;Is it?
  2824.                JB     SCROLL_PAGE            ;If yes, scroll page instead.
  2825.                MOV    BP,DIR_RECORD          ;Do the same for end of page.
  2826.                CMP    SI,PAGE_END
  2827.                JAE    SCROLL_PAGE
  2828.                CALL   MOVE_BAR
  2829.                RET
  2830.  
  2831. SCROLL_PAGE:   CALL   SCROLL
  2832.                RET
  2833.  
  2834. ;----------------------------------------------------;
  2835. ; This subroutine does the actual moving of the bar. ;
  2836. ;----------------------------------------------------;
  2837.  
  2838. MOVE_BAR:      MOV    DI,BAR_START           ;Remove old bar.
  2839.                MOV    CX,BAR_LENGTH
  2840.                MOV    BL,ATTR_TREE
  2841. NEXT_BAR:      CALL   WRITE_SCREEN
  2842.                LOOP   NEXT_BAR
  2843.  
  2844.                MOV    LINE,SI                ;And move bar to new line.
  2845.                MOV    BL,BAR_ATTRIBUTE
  2846.                CALL   GET_NAME
  2847.                MOV    SI,CUR_RECORD          ;Retrieve current record.
  2848.                MOV    DI,LINE                ;Retrieve line.
  2849.                MOV    BAR_LENGTH,0           ;Zero out bar length counter.
  2850. START_BAR:     LODSB
  2851.                CMP    AL,'\'                 ;Is it the root?
  2852.                JZ     SAVE_START             ;If yes, done here.
  2853.                INC    DI                     ;Increment bar pointer
  2854.                INC    DI                     ; past character as well.
  2855.                CMP    AL,196                 ;Is it horizontal bar character?
  2856.                JNZ    START_BAR              ;If no, find it.
  2857.                INC    SI                     ;Bump point to start of name.
  2858.  
  2859. SAVE_START:    MOV    BAR_START,DI           ;Save.
  2860. DISPLAY_BAR:   INC    BAR_LENGTH             ;Increment bar length counter.
  2861.                MOV    CX,1
  2862.                CALL   WRITE_SCREEN           ;Write the attribute.
  2863.                LODSB
  2864.                CMP    AL,0                   ;Are we at end of name?
  2865.                JNZ    DISPLAY_BAR            ;Continue until done.
  2866.                RET
  2867.  
  2868. ;-------------------------------------------------;
  2869. ; This subroutine displays the directory listing. ;
  2870. ;-------------------------------------------------;
  2871.  
  2872. UPDATE_SCREEN: XOR    BP,BP
  2873.                MOV    SI,CUR_OFFSET          ;Retrieve starting offset.
  2874.                MOV    DI,2*160+2             ;Point to row two of screen.
  2875.                MOV    BH,21                  ;21 lines to write.
  2876. NEXT_WRITE:    MOV    CX,40                  ;40 characters per line.
  2877. NEXT_CHAR:     LODSB                         ;Get a byte.
  2878.                MOV    BL,AL                  ;Save it in BL.
  2879.                CALL   WRITE_SCREEN           ;Write them.
  2880. ;----------------------FW--------------------------------------
  2881.                MOV    AX,BAR_START
  2882.                CMP    DI,AX                  ;FIND HIGHLIGH
  2883.                JB     MOVE_ATTR              ; ITEM
  2884.                ADD    AX,BAR_LENGTH          ; AND
  2885.                ADD    AX,BAR_LENGTH          ; LEAVE
  2886.                CMP    DI,AX                  ; IT
  2887.                JB     NOATTR                 ; ALONE
  2888. MOVE_ATTR:     MOV    BL,ATTR_TREE           ;ELSE USE TREE ATTR
  2889.                DEC    DI
  2890.                CALL   WRITE_SCREEN
  2891.                DEC    DI
  2892. NOATTR:
  2893. ;--------------------------------------------------------------
  2894.                LOOP   NEXT_CHAR
  2895.                ADD    DI,80                  ;Bump pointer to next line.
  2896.                DEC    BH                     ;Do all 21 lines.
  2897.                JNZ    NEXT_WRITE
  2898.                RET
  2899.  
  2900. ;------------------------------------------------------------;
  2901. ; This subroutine displays the directory by writing directly ;
  2902. ; to the screen buffer. To avoid screen noise (snow) on the  ;
  2903. ; color card, the horizontal retrace has to be monitored.    ;
  2904. ;------------------------------------------------------------;
  2905.  
  2906. WRITE_SCREEN:  MOV    DX,STATUS_REG          ;Retrieve status register.
  2907.                MOV    AX,VIDEO_SEG           ;Point to screen segment.
  2908.                MOV    ES,AX
  2909.  
  2910. HORZ_RET:      IN     AL,DX                  ;Get status.
  2911.                TEST   AL,1                   ;Is it low?
  2912.                JNZ    HORZ_RET               ;If not, wait until it is.
  2913.                CLI                           ;No more interrupts.
  2914.  
  2915. WAITS:         IN     AL,DX                  ;Get status.
  2916.                TEST   AL,1                   ;Is it high?
  2917.                JZ     WAITS                  ;If no, wait until it is.
  2918.                MOV    AL,BL                  ;Retrieve character; now it's OK
  2919.                STOSB                         ; to write to screen buffer.
  2920.                STI                           ;Interrupts back on.
  2921.                INC    DI                     ;Bump pointer past attribute.
  2922.                PUSH   CS
  2923.                POP    ES
  2924.                RET                           ;Return
  2925.  
  2926. ;-----------------------------------------------------------------------;
  2927. ; These two subroutine  clear either the messages or the entire screen. ;
  2928. ;-----------------------------------------------------------------------;
  2929.  
  2930. CLS:           XOR    CX,CX
  2931.                MOV    DX,184FH               ;Entire screen.
  2932.                CALL   CLEAR_WINDOW
  2933.  
  2934. CLEAR_MSG:     CALL   CURSOR_OFF
  2935.                MOV    CX,1529H               ;Row 22; column 41.
  2936.                MOV    DX,184FH               ;Row 24; column 79.
  2937.                PUSH   BP
  2938.                PUSH   BX
  2939.                MOV    BH,ATTR_MSGS           ;Clear MSGS AREA
  2940.                JMP    SHORT CLEAR_WINDOW2
  2941.  
  2942. CLEAR_LINE:    MOV    CX,1729H               ;Row 23; column 41.
  2943.                MOV    DX,174FH               ;Row 23; column 79.
  2944.                JMP    SHORT CLEAR_WINDOW
  2945.  
  2946. CLEAR_WINDOW:  PUSH   BP
  2947.                PUSH   BX
  2948.                MOV    BH,ATTR_TEXT           ;Clear with TEXT attribute.
  2949. CLEAR_WINDOW2: MOV    AX,600H
  2950.                INT    10H
  2951.                POP    BX
  2952.                POP    BP
  2953.                RET
  2954.  
  2955. ;-----------------------------------------;
  2956. ; These subroutines display the messages. ;
  2957. ;-----------------------------------------;
  2958.  
  2959. DISPLAY_TEXT:  CALL   SET_CURSOR             ;Move cursor.
  2960. GET_TEXT:      LODSB
  2961.                CMP    AL,0                   ;Zero marks end of string.
  2962.                JZ     END_TEXT
  2963. ;--------------------FW----------------------------------------
  2964.                MOV    BL,ATTR_TEXT
  2965. ;--------------------------------------------------------------
  2966.                CALL   WRITE_TEXT
  2967.                JMP    SHORT GET_TEXT
  2968. END_TEXT:      RET
  2969.  
  2970. WRITE_TEXT:    PUSH   SI                     ;BIOS does not save SI.
  2971.                MOV    AH,0EH                 ;Write teletype.
  2972.                INT    10H
  2973.                POP    SI
  2974.                RET
  2975.  
  2976. ;---------------------------------------------------------;
  2977. ; These four subroutines move the cursor, get the current ;
  2978. ; directory, beep the speaker or get a keystroke.         ;
  2979. ;---------------------------------------------------------;
  2980.  
  2981. SET_CURSOR:    PUSH   SI
  2982.                XOR    BH,BH                  ;Page zero.
  2983.                MOV    AH,2                   ;Set cursor.
  2984.                INT    10H
  2985.                POP    SI
  2986.                RET
  2987.  
  2988. BEEP:          MOV    DL,7                   ;Beep via DOS.
  2989.                MOV    AH,2
  2990.                INT    21H
  2991.                RET
  2992.  
  2993. READ_KEY:      MOV    AH,0                   ;Retrieve keystroke via BIOS.
  2994.                INT    16H
  2995.                RET
  2996.  
  2997. ;-----------------------------------------------;
  2998. ; These subroutines turn the cursor off and on. ;
  2999. ;-----------------------------------------------;
  3000.  
  3001. CURSOR_OFF:
  3002.                MOV    CX,2000H
  3003.                JMP    SHORT SET_TYPE
  3004.  
  3005. CURSOR_ON:     MOV    CX,CURSOR_TYPE
  3006.  
  3007. SET_TYPE:      MOV    AH,1
  3008.                INT    10H
  3009.                RET
  3010.  
  3011. ;----------------------------------------------;
  3012. ; This subroutine displays the count of files. ;
  3013. ;----------------------------------------------;
  3014.  
  3015. COUNT_DIRS:    MOV    DX,1802H               ;Row 24; column 2.
  3016.                CALL   SET_CURSOR
  3017.                MOV    AX,DIR_COUNT
  3018.                CALL   GET_DIR_COUNT
  3019.                MOV    SI,OFFSET DIR_MSG      ;Display directory count.
  3020.                CALL   GET_TEXT
  3021.                RET
  3022.  
  3023. ;------------------------------------------;
  3024. ; This subroutine converts hex to decimal. ;
  3025. ;------------------------------------------;
  3026.  
  3027. GET_COUNT:     MOV    AX,COUNT
  3028. GET_DIR_COUNT: MOV    BX,10                  ;Convert to decimal.
  3029.                XOR    CX,CX                  ;Zero in counter.
  3030. NEXT_COUNT:    XOR    DX,DX
  3031.                DIV    BX
  3032.                ADD    DL,'0'                 ;Convert to ASCII.
  3033.                PUSH   DX                     ;Save results.
  3034.                INC    CX                     ;Also increment count.
  3035.                CMP    AX,0                   ;Are we done?
  3036.                JNZ    NEXT_COUNT
  3037.  
  3038. NEXT_NUMBER:   POP    AX                     ;Retrieve numbers.
  3039.                CALL   WRITE_TEXT             ;And write them.
  3040.                LOOP   NEXT_NUMBER
  3041.                RET
  3042. ;------------------------------------------;
  3043. ; This subroutine MOVES TEST FROM SI TO DI ;
  3044. ;------------------------------------------;
  3045.  
  3046. MOVE_TEXT:     LODSB
  3047.                CMP    AL,0                   ;Zero marks end of string.
  3048.                JZ     MOVE_TEXT_END
  3049.                STOSB
  3050.                JMP    MOVE_TEXT
  3051. MOVE_TEXT_END: RET
  3052.  
  3053. ;---------------------------------------------;
  3054. ; This subroutine restores the current drive. ;
  3055. ;---------------------------------------------;
  3056.  
  3057. RESTORE_DRIVE: PUSH   DX
  3058.                MOV    DL,DEFAULT_DRIVE
  3059.                MOV    AH,0EH
  3060.                INT    21H
  3061.                POP    DX
  3062.                RET
  3063.  
  3064. ;------------------------------------;
  3065.  
  3066. DTA_AREA       DB     256 DUP (00)
  3067. DISK_BLOCK     LABEL  WORD
  3068. CURRENT_DIR    EQU    DISK_BLOCK+18
  3069. LEVEL_ADDRESS  EQU    CURRENT_DIR+65
  3070. DIRECTORIES    EQU    LEVEL_ADDRESS+100
  3071. DATA_BUFFER    EQU    LEVEL_ADDRESS+100
  3072. END_RESIDENT   EQU    DATA_BUFFER+(DATA_RECORD*500)
  3073.  
  3074. CODE ENDS
  3075. END  START
  3076.  
  3077.